Java Android:如何将JSON对象从AsncTask类传递到主类
我有一个Java Android:如何将JSON对象从AsncTask类传递到主类,java,android,json,android-asynctask,Java,Android,Json,Android Asynctask,我有一个JSONObject从AsyncTask类中的API调用接收数据。我想将该JSON对象传递给我的MainActivity类,以在GUI中显示JSONObject数据。我在一些搜索中找到了一些解决方案,并提出了一个接近的解决方案。但是当我从MainActivity类访问时,它会说JSONObject为空。我这里有什么不对的?这是最好的方法吗 下面是我的AsyncTask类 import android.content.Context; import android.os.AsyncTask
JSONObject
从AsyncTask
类中的API调用接收数据。我想将该JSON对象传递给我的MainActivity
类,以在GUI中显示JSONObject
数据。我在一些搜索中找到了一些解决方案,并提出了一个接近的解决方案。但是当我从MainActivity
类访问时,它会说JSONObject
为空。我这里有什么不对的?这是最好的方法吗
下面是我的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);
}
}
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
。我在这里做错了什么?在执行之前,您正在重新创建GetStationsAPICall
对象。因此,您的AsyncResponse
对象将为空
按如下方式更改代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GetStationsAPICall getStations = new GetStationsAPICall(this);
getStations.execute(method);
}
在执行之前,您正在重新创建
GetStationsAPICall
对象。因此,您的AsyncResponse
对象将为空
按如下方式更改代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GetStationsAPICall getStations = new GetStationsAPICall(this);
getStations.execute(method);
}
虽然我确信您已经找到了一个有效的解决方案,但我不建议将您的活动设置为一个可能泄漏它的侦听器(如果在返回结果之前按home按钮会发生什么情况?)。另外,如前所述,您遇到的主要问题是从
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);
}
}
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.
}
}
我做了不少修改,并发表了一些评论。这里需要注意的最重要的一点是,此活动不再是侦听器,因为我已经将此功能替换为。使用此功能,我可以注册任意数量的BroadcastReceiver
对象来处理AsyncTask的响应,而无需担心中断AsyncTask的进程
如您所见,我使用了一个IntentFilter
,让经理知道只有执行此操作的intent(“StationsAPI”)才能进入我注册的接收方(apistener
)。另外,我没有可能泄露活动的情况,我会在活动不再可见时立即注销接收器,并在活动再次可见时重新注册
GetStationsAPICall.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);
}
}
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.
}
}
导入android.content.Context;
导入android.os.AsyncTask;
导入android.util.Log;
导入android.content.Intent;
导入android.support.v4.content.LocalBroadcastManager;
导入org.apache.http.HttpEntity;
导入org.apache.http.HttpResponse;
导入org.apache.http.client.HttpClient;
导入org.apache.http.client.methods.HttpGet;
导入org.apache.http.impl.client.DefaultHttpClient;
导入org.apache.http.util.EntityUtils;
导入org.json.JSONObject;
/**
*Nisal于2017年9月13日创建。
*/
公共类GetStationsAPICall扩展异步任务{
LocalBroadcastManager LocalBroadcastManager;//这是将结果发送回“活动”的管理器
GetStationsAPICall(上下文ctx){
localBroadcastManager=localBroadcastManager.getInstance(ctx);//无论您在哪里调用它,它在整个应用程序中都是同一个对象。
}
@凌驾
受保护的字符串doInBackground(字符串…参数){
字符串方法=参数[0];
if(方法等于(“getStations”)){
试一试{
HttpClient=new DefaultHttpClient();
字符串getURL=”http://api.gate.com/?lang=en";
HttpGet-HttpGet=新的HttpGet(getURL);
httpGet.setHeader(“授权”、“承载690”);
HttpResponse response=client.execute(httpGet);
HttpEntity当前性=response.getEntity();
if(最近性!=null){
//解析响应。
字符串responseString=EntityUtils.toString(最近性);
Log.e(“响应”,响应预算;
return responseString;//这将是onPostExecute方法的参数
}
}捕获(例外e){
e、 printStackTrace();
}
}
返回null;
}
@凌驾
受保护的void onPostExecute(字符串obj){
本地广播管理器
.sendBroadcast(//发送带有响应的意图!
new Intent(“StationAPI”)//还记得IntentFilter吗?这里是声明发送Intent的位置。
.putExtra(“API_Response”,obj));//这是要发送给接收者的额外数据。
}
}
与上面的MainActivity
类一样,我已经用我所做的更改对部分进行了注释。JSONObject
类是不可打包的,因此我没有创建它,然后将其重新转换为可以放在Intent
中的内容,而是将其作为字符串
对象保留,并在doInBackground
方法
现在,无论何时调用
GetStationsAPICall
任务,您都应该在MainActivity
(或任何其他带有IntentFilter
用于“API\U响应”的接收器)中得到响应。尽管此解决方案本身并不完美(如果用户旋转设备会怎么样?),它应该有助于避免Android所提供的一些陷阱。尽管我确信您已经找到了一个可行的解决方案,但我不建议将您的活动放入一个可能会泄露它的侦听器中(如果在返回结果之前按home按钮会发生什么情况?)。此外,如前所述,您遇到的主要问题是从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);
}
}
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.
}
}
我用一些com做了很多更改