2017-09-13 33 views
0

我有一個JSONObjectAsyncTask類中的API調用接收。我想將該JSON對象傳遞給我的MainActivity類,以在GUI中顯示JSONObject數據。我在一些搜索中發現了一些解決方案,並提出了一個解決方案。但是,當我從MainActivity類訪問它說JSONObject爲空。我在這裏沒有錯?這是做這件事的最好方法嗎?Android:如何將JSON對象從AsncTask類傳遞到主類

以下是我AsyncTask

import android.content.Context; 
import android.os.AsyncTask; 
import android.util.Log; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.util.EntityUtils; 
import org.json.JSONObject; 

/** 
* Created by Nisal on 13-Sep-17. 
*/ 

public class GetStationsAPICall extends AsyncTask<String, Void, JSONObject> { 

    Context ctx; 
    JSONObject responseObj; 
    String result; 

    public interface AsyncResponse { 
     void processFinish(JSONObject output); 
    } 

    public AsyncResponse delegate = null; 

    public GetStationsAPICall(AsyncResponse delegate){ 
     this.delegate = delegate; 
    } 

// GetStationsAPICall(Context ctx){ 
//  this.ctx=ctx; 
// } 

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

     String method = params[0]; 

     if(method.equals("getStations")){ 

      try { 
       HttpClient client = new DefaultHttpClient(); 
       String getURL = "http://api.gate.com/?lang=en"; 
       HttpGet httpGet = new HttpGet(getURL); 
       httpGet .setHeader("Authorization", "Bearer 690"); 

       HttpResponse response = client.execute(httpGet); 
       HttpEntity resEntity = response.getEntity(); 
       if (resEntity != null) { 
        //parse response. 
        Log.e("Response", EntityUtils.toString(resEntity)); 
//     return "Successfully Connected!"; 
       }else{ 
//     return "Connection Failed!"; 
       } 

      } catch (Exception e) { 
       e.printStackTrace(); 
//    return "Connection Failed!"; 
      } 
     } 

     return null; 
    } 

    @Override 
    protected void onProgressUpdate(Void... values) { 
     super.onProgressUpdate(values); 
    } 

    @Override 
    protected void onPostExecute(JSONObject obj) { 
     delegate.processFinish(obj); 
    } 
} 

以下是我MainActivity

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.Toast; 

import org.json.JSONObject; 

public class MainActivity extends Activity implements GetStationsAPICall.AsyncResponse{ 

    Button btnSearch; 
    String method = "getStations"; 

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

     GetStationsAPICall getStations = new GetStationsAPICall(this); 
     new GetStationsAPICall(this).execute(method); 
    } 

    public void searchClicked(View view){ 
     Toast.makeText(MainActivity.this,"Search Clicked",Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    public void processFinish(JSONObject output) { 
     Toast.makeText(MainActivity.this,"ProcessFinish",Toast.LENGTH_SHORT).show(); 

     if(output != null){ 
      Toast.makeText(MainActivity.this,"not null",Toast.LENGTH_SHORT).show(); 
     }else{ 
      Toast.makeText(MainActivity.this," null",Toast.LENGTH_SHORT).show(); 
     } 
    } 
} 

我可以AsyncTask類中獲得JSONObject,但是當我試圖把它傳遞給MainActivity類在那裏使用它。 JSONObject變成null。我在這裏做錯了什麼?

+1

因爲你在doInBackground中只返回null而不是其他東西嗎? –

+0

查看我的回答 –

回答

1

雖然我敢肯定,你得到了一個有效的解決方案,我不建議讓您的活動成爲一個偵聽器可能泄漏它(如果按發生了什麼返回結果之前的主頁按鈕?)。另外,如前所述,您遇到的主要問題是您從doInBackground函數返回null。因此,讓我們解決這兩個問題現在:

MainActivity.java

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.Toast; 
import android.content.BroadcastReceiver; 
import android.content.IntentFilter; 
import android.support.v4.content.LocalBroadcastManager; 

import org.json.JSONObject; 

public class MainActivity extends Activity { 

    Button btnSearch; 
    String method = "getStations"; 
    BroadcastReceiver apiListener; 

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

     BroadcastReceiver apiListener = new BroadcastReceiver() { 
      @Override 
      public void onReceive(Context context, Intent intent) { 
       String output = intent.getStringExtra("API_Response); //Getting the string extra you input earlier in the AsyncTask. 
       Toast.makeText(MainActivity.this,"ProcessFinish",Toast.LENGTH_SHORT).show(); 

       if(output != null){ 
        Toast.makeText(MainActivity.this,"not null",Toast.LENGTH_SHORT).show(); 
       }else{ 
        Toast.makeText(MainActivity.this," null",Toast.LENGTH_SHORT).show(); 
       } 
      } 
     }; 

     //Since you are starting your AsyncTask here, might want to set up the receiver prior to calling the task. 
     LocalBroadcastManager.getInstance(this).registerReceiver(apiListener, new IntentFilter("")); 

     GetStationsAPICall getStations = new GetStationsAPICall(this); 
     new GetStationsAPICall(this).execute(method); 
    } 

    public void searchClicked(View view){ 
     Toast.makeText(MainActivity.this,"Search Clicked",Toast.LENGTH_SHORT).show(); 
    } 

    //Registers the receiver whenever this acitivty is currently being shown or about to. 
    @Override 
    public void onStart() { 
     super.onStart(); 
     LocalBroadcastManager.getInstance(this) 
      .registerReceiver(apiListener, new IntentFilter("StationsAPI")); //This is the intent filter this receiver will be listening for 
    } 

    //This stops the receiver from listening when the activity is no longer shown. 
    @Override 
    public void onStop() { 
     super.onStop(); 
     LocalBroadcastManager.getInstance(this).unregisterReceiver(apiListener); 
    } 
} 

我做了描述他們一些意見相當多的變化。這裏最重要的一點是,這個Activity不再是一個監聽器,因爲我已經替換了LocalBroadcastManager的功能。使用這個,我可以註冊許多BroadcastReceiver對象,因爲我希望處理AsyncTask的響應,而不用擔心中斷AsyncTask的過程。

正如你所看到的,我用了一個IntentFilter,讓經理知道,只有用這個動作(「StationsAPI」)意圖應該去我註冊的接收器(apiListener)。另外,所以我沒有可能泄漏活動的情況,一旦活動不再可見,就立即取消註冊接收方,並在再次可見時重新註冊。

GetStationsAPICall.java

import android.content.Context; 
import android.os.AsyncTask; 
import android.util.Log; 
import android.content.Intent; 
import android.support.v4.content.LocalBroadcastManager; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.util.EntityUtils; 
import org.json.JSONObject; 

/** 
* Created by Nisal on 13-Sep-17. 
*/ 

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

    LocalBroadcastManager localBroadcastManager; //This is the manager to send a result back to your activity 

    GetStationsAPICall(Context ctx){ 
     localBroadcastManager = LocalBroadcastManager.getInstance(ctx); //No matter where you call this, it is the same object throughout your app. 
    } 

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

     String method = params[0]; 

     if(method.equals("getStations")){ 

      try { 
       HttpClient client = new DefaultHttpClient(); 
       String getURL = "http://api.gate.com/?lang=en"; 
       HttpGet httpGet = new HttpGet(getURL); 
       httpGet .setHeader("Authorization", "Bearer 690"); 

       HttpResponse response = client.execute(httpGet); 
       HttpEntity resEntity = response.getEntity(); 
       if (resEntity != null) { 
        //parse response. 
        String responseString = EntityUtils.toString(resEntity); 
        Log.e("Response", responseString; 
        return responseString; //This will be the parameter of your onPostExecute method 
       } 

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

     return null; 
    } 

    @Override 
    protected void onPostExecute(String obj) { 
     localBroadcastManager 
      .sendBroadcast(//Sending the intent with the response! 
       new Intent("StationsAPI") //Remember that IntentFilter? Here is where you declare where to send intent. 
        .putExtra("API_Response", obj)); //This is the extra data you want to send to your receivers. 
    } 
} 

與上面的MainActivity類,我發表過評論的部分與我所做的更改。 JSONObject類不是可以分類的,所以不是創建它,而是將其轉換成我可以放置在Intent內的東西,我只是將它留作String對象,並在doInBackground方法中返回該值。

現在,只要你打電話給你GetStationsAPICall任務,你應該在你的MainActivity反應(或任何其他接收器與用於IntentFilter「API_Response」)。雖然這個解決方案本身並不完美(如果用戶旋轉了設備?),它應該有助於避免Android提供的一些陷阱。

1

在執行它之前,您正在重新創建GetStationsAPICall對象。所以你的AsyncResponse對象將是null。

更改您這樣的代碼:

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

     GetStationsAPICall getStations = new GetStationsAPICall(this); 
     getStations.execute(method); 
    } 
+0

謝謝。用你的答案和其他一些變化,我設法做到這一點。 –

+0

將它標記爲接受的答案,如果它真的爲你工作。它會幫助別人。 –

相關問題