通过(From)AsyncTask 向 MainActivity 发送意图

Posted

技术标签:

【中文标题】通过(From)AsyncTask 向 MainActivity 发送意图【英文标题】:Sending intent to MainActivity through (From) AsyncTask 【发布时间】:2017-01-25 18:44:37 【问题描述】:

我在 Stack Overflow 上查找了几个问题,用于向我的 MainActivity 发送 int 并将其显示在我的 TextView 上。但是尝试初始化活动或上下文不起作用.. 我得到的最新错误是:

致命异常:AsyncTask #1 进程:com.dahlstore.jsonparsingdemo,PID:32123 java.lang.RuntimeException:执行时发生错误 做背景() 在 android.os.AsyncTask$3.done(AsyncTask.java:309) 在 java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354) 在 java.util.concurrent.FutureTask.setException(FutureTask.java:223) 在 java.util.concurrent.FutureTask.run(FutureTask.java:242) 在 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 在 java.lang.Thread.run(Thread.java:818) 引起:java.lang.NullPointerException:尝试调用虚拟 方法'android.content.Context android.app.Activity.getApplicationContext()' 在一个空对象上 参考 在 com.dahlstore.jsonparsingdemo.JSONTask.doInBackground(JSONTask.java:63) 在 com.dahlstore.jsonparsingdemo.JSONTask.doInBackground(JSONTask.java:21) 在 android.os.AsyncTask$2.call(AsyncTask.java:295) 在 java.util.concurrent.FutureTask.run(FutureTask.java:237) 在 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 在 java.lang.Thread.run(Thread.java:818) 09-17 18:31:37.015 32123-32152/com.dahlstore.jsonparsingdemo E/Surface: getSlotFromBufferLocked:未知缓冲区:0xabea80a0

任何人都可以解释为什么即使我使用 Activity 也无法发送我的意图。

/*ROW21*/      public class JSONTask extends AsyncTask<String,String, String>

    OnDataSendToActivity dataSendToActivity;
    Activity activity;
    Intent intent;

    public JSONTask(MainActivity mainActivity) 
        dataSendToActivity = (OnDataSendToActivity)mainActivity;
    

    public JSONTask(Activity activity)
        this.activity = activity;
    

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

        HttpURLConnection connection = null;
        BufferedReader reader = null;

        try 
            URL url = new URL(params[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            InputStream stream = connection.getInputStream();

            reader = new BufferedReader(new InputStreamReader(stream));
            StringBuffer buffer = new StringBuffer();

            String line = "";
            while ((line = reader.readLine()) != null) 
                buffer.append(line);
            
            JSONObject parentObject = new JSONObject(buffer.toString());
            JSONObject query = parentObject.getJSONObject("query").optJSONObject("results").optJSONObject("channel").optJSONObject("item");
            String temperature = query.getJSONObject("condition").optString("temp");
            String text = query.getJSONObject("condition").optString("text");

            int code = query.getJSONObject("condition").optInt("code");
           **//ROW 63**  intent = new Intent(activity.getApplicationContext(),MainActivity.class); 

            intent.putExtra("code",code);

            return temperature + " °C " +" and "+ text;

         catch (MalformedURLException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
         catch (JSONException e) 
            e.printStackTrace();
         finally 
            if (connection != null) 
                connection.disconnect();
            
            try 
                if (reader != null) 
                    reader.close();
                
             catch (IOException e) 
                e.printStackTrace();
            
        
        return null;
    

    @Override
    protected void onPostExecute(String result) 
        super.onPostExecute(result);
        activity.startActivity(intent);
        dataSendToActivity.sendData(result);
    


MainActivity

public class MainActivity extends AppCompatActivity implements OnDataSendToActivity

    public TextView temperatureTextView,textView;

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

        temperatureTextView = (TextView) findViewById(R.id.temperatureTextView);
        textView = (TextView) findViewById(R.id.textView);

        new JSONTask(this).execute("https://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20woeid%3D906057%20and%20u%3D%27c%27&format=json");

        Intent intent = getIntent();
        if(intent!= null) 
            int code = getIntent().getIntExtra("code", 0);
            String codeToString = String.valueOf(code);
            textView.setText(codeToString);
         else 
            Toast.makeText(MainActivity.this, "Intent is null", Toast.LENGTH_SHORT).show();
        
    

    @Override
    public void sendData(String str) 
        temperatureTextView.setText(str);
    

更新的 JSONTASK.JAVA

public class JSONTask extends AsyncTask<String,String, String>
    OnDataSendToActivity dataSendToActivity;
    Context context;

    // single constructor to initialize both the context and dataSendToActivity
    public JSONTask(Context context)
        this.context = context;
        dataSendToActivity = (OnDataSendToActivity) ((Activity) context);
    

    @Override
    protected String doInBackground(String... params) 
        HttpURLConnection connection = null;
        BufferedReader reader = null;
        StringBuffer buffer = new StringBuffer();

        try 
            URL url = new URL(params[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            InputStream stream = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(stream));
            String line = "";
            while ((line = reader.readLine()) != null) 
                buffer.append(line);
            

         catch (MalformedURLException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
         finally 
            if (connection != null) 
                connection.disconnect();
            
            try 
                if (reader != null) 
                    reader.close();
                
             catch (IOException e) 
                e.printStackTrace();
            
        
        return buffer.toString();
    

    @Override
    protected void onPostExecute(String result) 
        try 
            JSONObject parentObject = new JSONObject(result);
            JSONObject query = parentObject.getJSONObject("query").optJSONObject("results").optJSONObject("channel").optJSONObject("item");
            String temperature = query.getJSONObject("condition").optString("temp");
            String text = query.getJSONObject("condition").optString("text");
            int code = query.getJSONObject("condition").optInt("code");
            temperature += " °C " +" and "+ text;

            Intent intent = new Intent(context, MainActivity.class);
            intent.putExtra("code", code);
            context.startActivity(intent);
            if(dataSendToActivity != null)
                dataSendToActivity.sendData(temperature);
            
         catch (JSONException e) 
            e.printStackTrace();
         catch (Exception e) 
            e.printStackTrace();
        
    

更新的 MAINACTIVITY

public class MainActivity extends AppCompatActivity implements OnDataSendToActivity

    public TextView temperatureTextView,textView;
    Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        temperatureTextView = (TextView) findViewById(R.id.temperatureTextView);
        textView = (TextView) findViewById(R.id.textView);
        intent = getIntent();
        new JSONTask(this).execute("https://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20woeid%3D906057%20and%20u%3D%27c%27&format=json");

    


    @Override
    public void sendData(String str) 
        temperatureTextView.setText(str);
    

【问题讨论】:

共享所有错误日志。 Aghazadeh 先生,我已经分享过了。 将断点添加到`dataSendToActivity = (OnDataSendToActivity)mainActivity;`,`dataSendToActivity = (OnDataSendToActivity)mainActivity;` 并检查。 原因:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法 'android.content.Context android.app.Activity.getApplicationContext()' 先生。 Aghazadeh,当不使用 Intent 时,onPostExecute 将结果发送到我的 MainActivity 没有任何问题。只有当我添加 Intent 函数来检索我的“int 代码”时,才会发生错误 【参考方案1】:

您收到错误消息,因为您的 activity 为空。这是因为你有两个构造函数。

// this is the constructor that is called
public JSONTask(MainActivity mainActivity) 
    dataSendToActivity = (OnDataSendToActivity)mainActivity;


// this is not called
public JSONTask(Activity activity)
    this.activity = activity;

所以你的 activity 变量永远不会被初始化。

查看我的更改,

public class JSONTask extends AsyncTask<String,String, String>
    OnDataSendToActivity dataSendToActivity;
    Context context;

    // single constructor to initialize both the context and dataSendToActivity
    public JSONTask(Context context)
        this.context = context;
        dataSendToActivity = (OnDataSendToActivity) ((Activity) context);
    

    @Override
    protected String doInBackground(String... params) 
        HttpURLConnection connection = null;
        BufferedReader reader = null;
        StringBuffer buffer = new StringBuffer();

        try 
            URL url = new URL(params[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            InputStream stream = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(stream));
            String line = "";
            while ((line = reader.readLine()) != null) 
                buffer.append(line);
            

         catch (MalformedURLException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
         finally 
            if (connection != null) 
                connection.disconnect();
            
            try 
                if (reader != null) 
                    reader.close();
                
             catch (IOException e) 
                e.printStackTrace();
            
        
        return buffer.toString();
    

    @Override
    protected void onPostExecute(String result) 
        try 
            JSONObject parentObject = new JSONObject(result);
            JSONObject query = parentObject.getJSONObject("query").optJSONObject("results").optJSONObject("channel").optJSONObject("item");
            String temperature = query.getJSONObject("condition").optString("temp");
            String text = query.getJSONObject("condition").optString("text");
            int code = query.getJSONObject("condition").optInt("code");
            temperature += " °C " +" and "+ text;

            if(dataSendToActivity != null)
                dataSendToActivity.sendData(temperature, code);
            
         catch (JSONException e) 
            e.printStackTrace();
         catch (Exception e) 
            e.printStackTrace();
        
    

在你的MainActivity

public class MainActivity extends AppCompatActivity implements OnDataSendToActivity 

    public TextView temperatureTextView,textView;

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

        temperatureTextView = (TextView) findViewById(R.id.temperatureTextView);
        textView = (TextView) findViewById(R.id.textView);

        new JSONTask(this).execute("https://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20woeid%3D906057%20and%20u%3D%27c%27&format=json");
    

    @Override
    public void sendData(String str, String code) 
        temperatureTextView.setText(str);
        textView.setText(code);
    

你的OnDataSendToActivity界面会变成,

public interface OnDataSendToActivity 
    void sendData(String str, String code);

【讨论】:

非常感谢 K Neeraj Lal 先生。不幸的是,我仍然遇到两个错误。第一个是我不能再在我的 postExecute 方法中返回“温度 +”°C“+”和“+文本”,因为它是 void。将它从 void 更改为 String 会给我“不兼容的返回类型”。第二个错误:activity inside of: Intent intent = new Intent(activity, MainActivity.class);使用上面的代码时无法解析为符号。我想添加 public JSONTask(Activity activity) this.activity = activity; 在我的代码中? 我的错。见编辑。没有使用 IDE 编写代码。 不,您不必添加该构造函数。 是的,按照您当前的架构,这是预期的。只需要一些小的调整。查看编辑。 非常感谢您的帮助!我真的很感激,现在一切都很好!【参考方案2】:

您实际上不必使用意图将您的“代码”发送到活动。在您的 doInBackground 中,将您的“代码”放入一个字符串变量中(您需要正确解析它),然后将该字符串作为返回值的参数。

然后在 postExecute(String result) 中,变量 result 应该是你从 doInBackground 返回的值。 dataSendToActivity.sendData(result) 现在应该可以正常工作了。

【讨论】:

这是一个非常好的主意。我知道并已通过我的 postExecute 方法成功发送了“代码”。问题是我的 MainActivity 中的一个函数应该用作索引,因此我可以从我的可绘制文件夹中获取正确的图像。我无法使用 dataSendToActivity 返回我的“代码”值。如您所见,那是因为我现在要返回两个字符串(温度和文本)。意图 i= getIntent(); int value= i.getIntExtra("intVariableName", 0);可绘制的 weatherIconDrawable = getResources().getDrawable(value); weatherIconImageView.setImageDrawable(weatherIconDrawable); 我明白了。你可以完全删除意图。然后将“代码”值附加到 doInBackground 中的返回字符串。在 postExecute 中,您可以解析值,以便代码转到 textView 而温度转到 temperatureTextView。 您需要检查 Neeraj 评论,您的活动参考需要修复。【参考方案3】:

我认为错误是您在异步中使用 getIntExtra。而不是使用 putIntExtra 将变量保存在意图中。

Put 用于存储值,getIntent 函数用于从 Intent 中获取数据。

使用这条线,

intent = new Intent(getApplicationContext(),MainActivity.class); 

intent = new Intent(YourClassName.class,MainActivity.class); 

【讨论】:

我没有 putIntExtra 作为替代方案。但是我只是改为 putExtra 而不是 getIntExtra 并更新了错误消息。 @user3506 我在答案中编辑了一行。试试看。 不幸的是,这两个都不起作用。但感谢您的努力! @user3506 编辑后您仍然在此行收到 NulPointerError? 不,Puri 先生,我使用了@K Neeraj Lal 的建议,效果很好。我只需要找出为什么我的应用程序会一遍又一遍地重新启动......你看到问题了吗? (大约五分钟前更新代码)

以上是关于通过(From)AsyncTask 向 MainActivity 发送意图的主要内容,如果未能解决你的问题,请参考以下文章

通过 AsyncTask 下载图像并将其显示在 Imageview 中而不存储在 sdcard 中

android asynctask向ui发送回调[重复]

通过AsyncTask下载图像并将其显示在Imageview中而不存储在SD卡中

详解AsyncTask的使用

AsyncTask的使用

在向多个表添加数据行时实现AsyncTask