Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/215.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android:如何将JSON对象从AsncTask类传递到主类_Java_Android_Json_Android Asynctask - Fatal编程技术网

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做了很多更改