2017-11-30 3 views
0

POSTHttpURLConnection으로 만드는 기본 Android 앱을 만들고 있습니다. 내 웹 API에서 응답 메시지를 반환하고 싶습니다.doInBackground가 변수를 업데이트하지 않습니다.

내 MainActivity.java

public class MainActivity extends AppCompatActivity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     final TextView mTextView = findViewById(R.id.textView); 
     AsyncExample asyncExample = new AsyncExample(); 
     asyncExample.execute(); 
     mTextView.setText(asyncExample.getResponseMsg()); 
    } 
} 

응용 프로그램을 실행 한 후 내 AsyncExample.java

class AsyncExample extends AsyncTask<Void, Void, Void> { 
    private HttpURLConnection con; 
    private String responseMsg; 

    protected void onPreExecute() { 
     responseMsg = "empty message"; 
    } 

    @Override 
    protected Void doInBackground(Void... params) { 
     String urlParameters = "param1=data1"; 

     byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8")); 
     int postDataLength = postData.length; 
     String request = "http://192.168.1.30:6262"; 
     URL url = null; 
     try { 
      url = new URL(request); 
      con = (HttpURLConnection) url.openConnection(); 
      con.setDoOutput(true); 
      con.setInstanceFollowRedirects(false); 
      con.setRequestMethod("POST"); 
      con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 
      con.setRequestProperty("charset", "utf-8"); 
      con.setRequestProperty("Content-Length", Integer.toString(postDataLength)); 
      responseMsg = con.getResponseMessage(); 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public String getResponseMsg() { 
     return responseMsg; 
    } 
} 

, 내 TextViewempty message를 얻을. 왜 내 doInBackground 업데이트되지 않습니다? con.getResponseMessage()null이라도 업데이트해야합니까?

+0

해당 문자열 응답을 저장 doinbackground 방법에서와 onPostexecute에서 응답을 반환해야합니다에 대한 원하고 지금 당신이 그 문자열 응답에 액세스 할 수 모두를 말할 것이다 –

+0

아직 또 다른 ... [IT IS MULITHREADING] (https://ideone.com/PPHi95) – Selvin

답변

1

문제는 당신 AsyncTask가 비동기 적으로 실행되는 것을, 당신 동안 값을 즉시 검색하십시오. 이것을 약간 다르게 구현해야합니다. AsyncTask API를 활용하여 UI 스레드에서 콜백을 게시합니다. 당신은 당신의 AsyncTask

class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> { 

    @Override 
    protected void onPreExecute() { 
     myTextView.setText("progress started"); 
    } 

    @Override 
    protected String doInBackground(final Void... voids) { 
     String s = amazingCallToBackend(); 
     return s; 
    } 

    @Override 
    protected void onPostExecute(final String s) { 
     myTextView.setText(s); 
    } 
} 

에 직접 TextView를 업데이트 할 수 있습니다 또는 당신은 단지 값을 원하는 경우, 당신은

interface Callback { 
    void onValueReceived(String value); 
    void onFailure(); 
} 

class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> { 

    private Callback callback; 

    MyAwesomeAsyncTask(final Callback callback) { 
     this.callback = callback; 
    } 

    @Override 
    protected String doInBackground(final Void... voids) { 
     String s = amazingCallToBackend(); 
     return s; 
    } 

    @Override 
    protected void onPostExecute(final String s) { 
     callback.onValueReceived(s); 
    } 
} 
처럼 뭔가를 당신에게 가치를 제공 할 것이다 비동기 작업에 콜백을 전달할 수 있습니다

다음은,

Callback callback = new Callback() { 
     @Override 
     public void onValueReceived(final String value) { 

     } 

     @Override 
     public void onFailure() { 

     } 
    }; 

new MyAwesomeAsyncTask(callback).execute(); 

그러나 그것을 만드는 어떤 이유로 활동/단편 사라 졌는지/당신의 비동기 전에 완료하기 때문에주의 방법 작업이 완료되면 메모리 누수가 발생할 수 있습니다.

빠른 Google 검색은 AsyncTask를 누출 메모리 :

+0

첫 번째 방법을 시도 할 것입니다. myTextView는 어디에 정의해야합니까? – BeGreen

+0

textView는 활동의 필드이고 AsyncTask는 동일한 활동의 ​​내부 클래스입니다. 또는 두 번째 예제에서 Callback을 통과 한 것처럼 TextView를 전달할 수도 있습니다. – elmorabea

+0

'Callback' 인터페이스로 새로운'MyAwesomeAsyncTask'를 어떻게 만듭니 까? – BeGreen

0

봅니다

public class MainActivity extends AppCompatActivity { 
TextView mTextView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    mTextView = findViewById(R.id.textView); 
    AsyncExample asyncExample = new AsyncExample(this,mTextView); 
    asyncExample.execute(); 
    } 
} 

AsyncTask를이

MainActivity처럼 수행하는

class AsyncExample extends AsyncTask<Void, Void, Void> { 
    private HttpURLConnection con; 
    private String responseMsg; 
    private MainActivity mContext; 
    TextView mTextView; 

    public AsyncExample (MainActivity context, TextView textView) { 
     mContext = context; 
     mTextView = textView; 
    } 

    protected void onPreExecute() { 
     responseMsg = "empty message"; 
    } 

    @RequiresApi(api = Build.VERSION_CODES.KITKAT) 
    @Override 
    protected Void doInBackground(Void... params) { 
     String urlParameters = "param1=data1"; 

     byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8); 
     int postDataLength = postData.length; 
     String request = "http://192.168.1.30:6262"; 
     URL url = null; 
     try { 
      url = new URL(request); 
      con = (HttpURLConnection) url.openConnection(); 
      con.setDoOutput(true); 
      con.setInstanceFollowRedirects(false); 
      con.setRequestMethod("POST"); 
      con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 
      con.setRequestProperty("charset", "utf-8"); 
      con.setRequestProperty("Content-Length", Integer.toString(postDataLength)); 
      responseMsg = con.getResponseMessage(); 
      mContext.runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        mTextView.setText(responseMsg); 
       } 
      }); 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public String getResponseMsg() { 
     return responseMsg; 
    } 
} 
+0

그것은'runOnUiThread' 메소드를 해결할 수 없다고 말합니다. – BeGreen

+0

코드를 지금 사용해보십시오. Activity의 컨텍스트를 AsyncTask에 전달하여 runOnUiThread 메서드를 얻을 수있게했습니다. – QEMU

+0

은 여전히'runOnUiThread'와 같은 오류이고'mTextView' 같은 오류 – BeGreen

1

AsyncTask를이 게시물에 배경 3. 3 기본 방법 preexecute에 1. 2. 할 일이있다 실행

실행 후 :

응답은 doinbackground에서 가져온 후 실행됩니다. 결과를 처리 할 수 ​​있습니다. runnable 메서드를 사용하여 텍스트 뷰를 업데이트하십시오. ui

1

onPostExecute() 메서드를 재정 의하여 텍스트를 반환하십시오. 주 활동에서 비동기 작업 실행을 완료 한 후 TextView를 업데이트하는 방법을 만듭니다. Main Thread이 실행 및 텍스트보기 설정을 일시 중지하지 않았지만 비동기 작업이 아직 실행을 완료하지 않아 문자열이 비어 있기 때문에 아무 것도 표시되지 않습니다. 텍스트보기를 설정하기 전에 비동기 작업이 완료 될 때까지 기다리십시오.

String str_result= new RunInBackGround().execute().get(); 

Refer to this for more information.

+0

그래서 기본적으로'get' 메소드는'onPostExecute'의 반환 값을 찾을 것입니까? 'onPostExecute'가'String'을 리턴 할 수 없다면, 메소드를 오버라이드 할 수 없다고 말합니다. – BeGreen

+0

당신은 PostExecute로부터 String을 돌려 줄 수 없을 것입니다. Async Task 클래스를 Inner 클래스로 만들 수 있습니다. MainActivity 클래스가있는 클래스의 내부 클래스를 호출하고 내부 클래스의 메서드를 호출하여 Inner Aysnc Task 클래스에서 textView를 업데이트합니다. 도움이 필요하면이 코드를 참조하십시오. https://github.com/Pronoy999/NewsApp/blob/master/app/src/main/java/com/news/mukhe/newsapp/NewsActivity.java –

2

귀하의 doInBackground 방법은 실행 시간이 걸립니다. 즉시 mTextView.setText(asyncExample.getResponseMsg());으로 전화를 걸었지만 asynctask은 아직 완료되지 않았습니다. doInBackground가 끝날 때까지 기다렸다가 으로 전화하면 onPostExecute 방법으로 처리 할 수 ​​있습니다.

+0

알았습니다. 시도 할 때 HTTP 요청이 완료되지 않았 음을 이해합니다. 내 문자열에 액세스 할 수 있습니다. TextView를 업데이트하는 대신'OnPostExecute'에 값을 반환하려면 어떻게해야합니까? – BeGreen

+0

'onPostExecute'에서 값을 반환 할 수 없습니다. 내가 생각할 수있는 한 가지 방법은'CountDownLatch'를 사용하는 것입니다.하지만 과잉입니다. AsyncTask를 다루는 것은 엉망입니다. RxJava가이 문제를 해결합니다. – Sunny

0

여러 가지 방법으로 할 수 있습니다. 기존 코드의 변경 사항을 무시할 수있는 방법을 제안하려고합니다.

AsyncExample 내 전역 변수로 mTextView를 재정의하고 onPostExecute() 메서드를 선언하고 해당 onPostExecute() 메서드 내에서 mTextView를 doInBackground() 메서드에서 전달 된 값으로 업데이트합니다. 여기서 responseMsg는 onPostExecute() 메소드에 의해 String 값 (결과)으로 포착 된 doInBackground() ground의 끝]. 그러나 onPreExecute() 메서드를 재정의하는 것이 좋습니다.

이렇게하려면 MainActivity.

public class MainActivity extends AppCompatActivity { 
TextView mTextView; //declare mTextView outside the onCreate() method as a Global String variable. 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     mTextView = findViewById(R.id.textView); 
     AsyncExample asyncExample = new AsyncExample(); 
     asyncExample.execute(); 
    } 
} 

당신의 AsyncTask를 같은 활동의 내부 급하고 다음과 같이 편집하십시오 : 다음과 같이 자바해야

class AsyncExample extends AsyncTask<Void, Void, Void> { 
    private HttpURLConnection con; 
    private String responseMsg; 

    @Override   // Its a good practice to Override the onPreExecute() method. 
    protected void onPreExecute() { 
     responseMsg = "empty message"; 
    } 

    @Override 
    protected String doInBackground(String... params) { 
     String urlParameters = "param1=data1"; 

     byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8")); 
     int postDataLength = postData.length; 
     String request = "http://192.168.1.30:6262"; 
     URL url = null; 
     try { 
      url = new URL(request); 
      con = (HttpURLConnection) url.openConnection(); 
      con.setDoOutput(true); 
      con.setInstanceFollowRedirects(false); 
      con.setRequestMethod("POST"); 
      con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 
      con.setRequestProperty("charset", "utf-8"); 
      con.setRequestProperty("Content-Length", Integer.toString(postDataLength)); 
      responseMsg = con.getResponseMessage(); 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return responseMsg; //return the value of responseMsg 
    } 

     @Override  //override onPostExecute() method 
     protected void onPostExecute(String result) { //receive the value to be set to mTextView which is returned by the doInBackground() method. 
      mTextView.setText(result); 
    } 

} 
관련 문제