2016-03-22 21 views
0

私のアプリケーションを動作させるために、私のサーバーからデータを取得する必要があります。これを行うために、私はPOSTを使用します。限り、私は知っているように、私はメインスレッドにすることはできませんスレッドでそのデータを要求する必要があります。私は、UIスレッドで定義された変数に、私が受け取っているデータを置くためにちょっとdiffcultを見つけています。だから、私の質問は、それを行うための最善の方法は何ですか? AsyncTaskの内部で呼び出されるセッターを使用して、たとえばメインアクティビティで定義された変数の値を設定するのは正しいですか?または、このオプションが良いかもしれませんか?サーバーからデータをリクエストする最も良い方法

Thread nt = new Thread(){ 
     @Override 
    public void run(){ 

      try{ 

       //get data with POST and then something like main.setValue(data); 
      }catch(Exception e){ 

       e.printStackTrace(); 
      } 
     } 

    }; 
    nt.start(); 

私はそれをアーカイブするためにインタフェースを使用するかもしれないと読んだことがありますが、それは私がまだよく理解していない概念です。私は直接データを返すメソッドを使用したいと思いますが、私が知る限りは不可能です。 あなたの時間のためのThabks!

EDIT:NoChinDeluxe回答に応じて新たなコード:

public class LoginHandler { 

public static class Login extends AsyncTask<String, String, Integer> { 


    LoginCallback listener; 

    @Override 
    protected Integer doInBackground(String... params) { 


     URL url; 

     postDataParams.put("name", params[0]); 
     HashMap<String, String> postDataParams = new HashMap<String, String>(); 
     postDataParams.put("password", params[1]); 

     try { 

      url = new URL("http://mashiron.xyz/_03z/gmpia/proc.php"); 

      HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
      conn.setReadTimeout(15000); 
      conn.setConnectTimeout(15000); 
      conn.setRequestMethod("POST"); 
      conn.setDoInput(true); 
      conn.setDoOutput(true); 


      OutputStream os = conn.getOutputStream(); 
      BufferedWriter writer = new BufferedWriter(
        new OutputStreamWriter(os, "UTF-8")); 

      writer.write(HttpHandler.getPostDataString(postDataParams)); 
      writer.flush(); 
      writer.close(); 
      os.close(); 
      System.out.println("Respuesta: "+conn.getResponseCode()); 
      return conn.getResponseCode(); 

     } catch (Exception e) { 
      e.printStackTrace(); 

      return 404; 
     } 
    } 

    protected void onPostExecute(int result){ 
     System.out.println("Respuesta 2: "+result); 

     listener.onResultReceived(result); 
    } 

} 



public interface LoginCallback { 

    void onResultReceived(int result); 
} 

}

EDIT:NoChinDeluxeための追加例外:

3月24日17:38:09.072 13312から13312/COM。 pazzazz.geomoments E/AndroidRuntime:致命的な例外:メイン プロセス:com.pitazzo.geomoments、PID:13312 java.lang.NullPointerException:インタフェースメソッド 'void com.pitazzo.geomo (null)オブジェクト参照のnull.Handlers $ Login.allPostExecute(LoginHandler.java:65) com.pitazzo.geomoments.Handlers.LoginHandlerでログインします。 LoginHandler $ Login.onPostExecute(LoginHandler.java:17) とandroid.os.AsyncTask.finish(AsyncTask.java:636) at android.os.AsyncTask.access $ 500(AsyncTask.java:177) にandroid.os .AsyncTask $ InternalHandler.handleMessage(AsyncTask.java:653)android.os.Handler.dispatchMessage(Handler.java:102)の のandroid.os.Looper.loop(Looper.java:135) android.app .ActivityThread.main(Activi tyThread.java:5300) at java.lang.reflect.Method.invoke(ネイティブメソッド) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit com.android.internal.os.ZygoteInit.mainで$ MethodAndArgsCaller.run(ZygoteInit.java:904) (ZygoteInit.java:699)

EDIT:NoChainDeluxe

public class LoginActivity extends AppCompatActivity implements LoginHandler.LoginCallback{ 

EditText name; 
EditText password; 
Button login; 
int code; 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.login_activity); 

    /* 
    if(logueado){ 

    } 


    */ 


    name = (EditText) findViewById(R.id.loginuser); 
    password = (EditText) findViewById(R.id.loginpassword); 
    login = (Button) findViewById(R.id.loginlogin); 

    login.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

      String params[] = {name.getText().toString(), password.getText().toString()}; 
      System.out.println("Params: "+params.toString()); 

      new LoginHandler.Login().execute(params); 
      System.out.println("Respuesta 4: "+code); 

      if(code == 200){ 
       Toast toast1 = 
         Toast.makeText(getApplicationContext(), 
           "Iniciado sesión", Toast.LENGTH_SHORT); 

       toast1.show(); 
      }else{ 

       Toast toast1 = 
         Toast.makeText(getApplicationContext(), 
           "Nombre de usuario y/o contraseña incorrectos: "+code, Toast.LENGTH_SHORT); 

       toast1.show(); 

      } 

     } 
    }); 

} 

public void onResultReceived(int resultado) { 
    code = resultado; 
    System.out.println("Respuesta 3: "+code); 

} 

}のためのより多くのコード

+0

必要に応じてAysncTaskを使用してください。あなたがそれを使うなら、セッターは必要ありません。 AsyncTaskのonPostExecute()メソッドでは、UIを更新できます。 –

答えて

3

HttpURLConnectionを使用してウェブコールをAsyncTaskの内部で行い、その結果をコールバックアクティビティにコールバックを介して戻すことをお勧めします。

最初に理解しておきたいことは、AsyncTaskのコールバックを正しく使用する方法です。ここでは、コールバックインターフェースを定義する例AsyncTask次のとおりです。この作品

import android.os.AsyncTask; 

public class TestTask extends AsyncTask<String, Void, String> { 

    TestTaskCallback listener; 

    public TestTask(TestTaskCallback listener) { 
     this.listener = listener; 
    } 

    protected String doInBackground(String... args) { 

     String input = args[0]; 
     String output = "simulated return value"; 

     return output; 
    } 

    protected void onPostExecute(String result) { 
     listener.onResultReceived(result); 
    } 

    public interface TestTaskCallback { 
     void onResultReceived(String result); 
    } 
} 

方法があり、あなたは、あなたの活動に実装するパブリックインターフェイスを定義します。これは、それを介して送信されるすべてのデータを待っている「リスナー」として機能します。 TestTaskCallbackというインターフェースを定義しているのは、AsyncTaskのデータを私たちの呼び出しアクティビティに送るからです。

アクティビティでは、このインターフェイスを実装して、私たちがそれを作成するときに私たちの実装への参照をタスクに渡す必要があります。そうすることで、タスクが起動すると、結果を送信する場所がわかります。これはアクティビティに戻ります。実装例は次のようになります。

public class TestActivity extends AppCompatActivity implements TestTask.TestTaskCallback { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.your_layout); 

     new TestTask(this).execute("Some input"); 

    } 

    public void onResultReceived(String result) { 
     Log.d("TEST TASK RESULT", result); 
    } 
} 

だから、私たちの活動は、我々のAsyncTask内で定義されたインタフェースを実装しており、私たちのAsyncTaskは(コンストラクタで渡された)この実装への参照を取得してにデータを送信していることに気づきますそれはonPostExecute()方法です。これにより、結果をメインのUIスレッドに送信できるようになり、アクティビティを適切に更新することができます。

残っているのは、実際にウェブ通話をすることだけです。これにはHttpURLConnectionを使用することをお勧めします。あなたはこのコードをAsyncTaskdoInBackground()メソッドの中に入れます。

設定したWebサービスコールの例を示します。 JSONレスポンスを取得するためのWebサービスコールの作成方法を示します。

//The JSON we will get back as a response from the server 
JSONObject jsonResponse = null; 

//Http connections and data streams 
URL url; 
HttpURLConnection httpURLConnection = null; 
OutputStreamWriter outputStreamWriter = null; 

try { 

    //open connection to the server 
     url = new URL("your_url_to_web_service"); 
     httpURLConnection = (HttpURLConnection) url.openConnection(); 

     //set request properties 
     httpURLConnection.setDoOutput(true); //defaults request method to POST 
     httpURLConnection.setDoInput(true); //allow input to this HttpURLConnection 
     httpURLConnection.setRequestProperty("Content-Type", "application/json"); //header params 
     httpURLConnection.setRequestProperty("Accept", "application/json"); //header params 
     httpURLConnection.setFixedLengthStreamingMode(jsonToSend.toString().getBytes().length); //header param "content-length" 

     //open output stream and POST our JSON data to server 
     outputStreamWriter = new OutputStreamWriter(httpURLConnection.getOutputStream()); 
     outputStreamWriter.write(jsonToSend.toString()); 
     outputStreamWriter.flush(); //flush the stream when we're finished writing to make sure all bytes get to their destination 

     //prepare input buffer and get the http response from server 
     StringBuilder stringBuilder = new StringBuilder(); 
     int responseCode = httpURLConnection.getResponseCode(); 

     //Check to make sure we got a valid status response from the server, 
     //then get the server JSON response if we did. 
     if(responseCode == HttpURLConnection.HTTP_OK) { 

      //read in each line of the response to the input buffer 
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(),"utf-8")); 
      String line; 
      while ((line = bufferedReader.readLine()) != null) { 
       stringBuilder.append(line).append("\n"); 
      } 

      bufferedReader.close(); //close out the input stream 

      try { 
       //Copy the JSON response to a local JSONObject 
       jsonResponse = new JSONObject(stringBuilder.toString()); 
      } catch (JSONException je) { 
       je.printStackTrace(); 
      } 
     } 

} catch (IOException ioe) { 
    ioe.printStackTrace(); 
} finally { 
    if(httpURLConnection != null) { 
     httpURLConnection.disconnect(); //close out our http connection 
    } 

    if(outputStreamWriter != null) { 
     try { 
      outputStreamWriter.close(); //close our output stream 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 
    } 
} 

//Return the JSON response from the server. 
return jsonResponse; 

これは、あなたがしようとしていることを正確に行うために必要なものです。私はこれが一度にあなたに投げ込む情報のトンですが、あなたが時間をかけてそれを少しずつ練習すれば、結局はそれほど難しくないことがわかります。実際には非常に強力なツールです。 Androidアプリを常時プログラミングしていますか?

これが役に立ちます。あなたがまだ完全に理解していない部分については、お気軽に質問してください!

+0

AWSOME!本当にありがとう、私はそれを試し、あなたに何か質問をお知らせさせていただきありがとうございました! – pitazzo

+0

こんにちはNoChinDeluxe!私は問題を試しています。あなたが言ったように自分のasyntaskを定義し、またコールバックインターフェイスも定義しました。しかし、リスナーが働いていないことに気付きました。いくつかのデバッグメッセージの助けを借りて、問題は私のonPostExecute()メソッドが呼び出されなかったことであることがわかりました。彼の長さのために、私は私の質問の新しい編集に私のコードを掲載します、私の間違いを見つけることができれば幸いです。 – pitazzo

+0

tryブロック内の印刷行については、 'System.out.println(" Respuesta: "+ conn。getResponseCode()); '< - これは呼び出されますか?そうでなければ、あなたのタスク( ''いつでも忘れること) '' execute() 'を呼び出すことを忘れているかもしれません。 – NoChinDeluxe

1

非同期タスクを使用してあなたのUIスレッドにデータを変換するには、onPostExecute()を使用して、アクティビティーのクラスの結果を設定してください。

0

エラーは、バックグラウンドスレッドからUI要素にアクセスしているために発生しています。

AsyncTaskは別々のスレッド であなたのタスクを実行するスレッドプールベースのAPIですが、あなたのUI部分はロジックonPostExecute()

に入れUIに通常すべての変更を更新するために、 UI thread を呼び出したスレッドで実行されます

注:一貫性のあるhttp APIを入手するにはokhttpを使用し、http2もサポートしています.Github wikiは非常に役に立ちます。例としてhereを確認してください。

関連する問題