如何从 android 中的 AsyncTask 获取 UI 参考

Posted

技术标签:

【中文标题】如何从 android 中的 AsyncTask 获取 UI 参考【英文标题】:How do I get UI reference from AsyncTask in android 【发布时间】:2020-08-28 19:38:54 【问题描述】:

我正在尝试在 android 中学习多线程,尽管当我在 Logcat 窗口上打印数据时我的代码工作正常,但是每当我尝试从 asynctask 更新组件时,我的应用程序崩溃并给我一个空点异常。

它给了我以下错误

 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.append(java.lang.CharSequence)' on a null object reference
    at com.shivam.asynctasks.MainActivity.logm(MainActivity.java:41)

第 41 行

textView.append(message + "\n");

我的代码

    public class MainActivity extends AppCompatActivity 

    Button button ;
    TextView textView;
    String TAG = "MyTag";

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

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

        button.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                String TAG ="MyTag";
                Log.d(TAG,"OnClick Thread Started");

                MyTask mytask =new MyTask();
                mytask.execute("Red","Black","Yellow","Blue","Orange");
            
        );
    


    public void logm(String message) 
        Log.d(TAG, message);
        textView.append(message + "\n");
    


class MyTask extends AsyncTask<String,String,String>

    @Override
    protected String doInBackground(String... strings) 
        String TAG = "MyTag";

        for (String value :
                strings) 
            try 
                Thread.sleep(3000);
             catch (InterruptedException e) 
                e.printStackTrace();
            

            Log.d(TAG, "do in Background  : "+value);
            publishProgress(value);

        

        return null;
    

    @Override
    protected void onProgressUpdate(String... values) 
        super.onProgressUpdate(values);
         MainActivity mainActivity =new MainActivity();

        for (String color : values) 

            mainActivity.logm(color);
        
    

【问题讨论】:

您正在使用new MainActivity() 创建一个新活动...您需要访问现有的活动。 【参考方案1】:

您需要引用您的活动而不是创建新活动。在这里你可以看到。

import android.os.AsyncTask;

public class MainActivity extends AppCompatActivity 

    Button button ;
    TextView textView;
    String TAG = "MyTag";

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

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

        button.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                String TAG ="MyTag";
                Log.d(TAG,"OnClick Thread Started");

                MyTask mytask =new MyTask(this);
                mytask.execute("Red","Black","Yellow","Blue","Orange");
            
        );
    


    public void logm(String message) 
        Log.d(TAG, message);
        textView.append(message + "\n");
    


class MyTask extends AsyncTask<String,String,String> 
    WeakReference<MainActivity> mainActivityRef;
    public MyTask(MainActivity activity)
        mainActivityRef = new WeakReference<MainActivity>(activity);
    
    @Override
    protected String doInBackground(String... strings) 
        String TAG = "MyTag";

        for (String value :
                strings) 
            try 
                Thread.sleep(3000);
             catch (InterruptedException e) 
                e.printStackTrace();
            

            Log.d(TAG, "do in Background  : "+value);
            publishProgress(value);

        

        return null;
    

    @Override
    protected void onProgressUpdate(String... values) 
        super.onProgressUpdate(values);
        MainActivity mainActivity = mainActivityRef.get();

        for (String color : values) 
            mainActivity.logm(color);
        
    

【讨论】:

你的代码有效,但它给了我一个警告这个字段在这里泄漏了一个上下文对象 class MyTask extends AsyncTask MainActivity mainActivity;//在这一行你能解释一下为什么显示此警告 因为当asynctask更新进度时,activity可能已经被销毁了。我们不应该保留上下文引用。在这些情况下我们需要使用弱引用,请查看更新的答案 只是我尝试使用 mainActivityRef.logm(color); 的另一件事;访问该方法但无法这样做 //cannot reslove method logm(java.lang.string). 您需要获取参考。你可以这样做:mainActivityRef.get().logm(color);【参考方案2】:

您收到错误是因为您在未启动 textView 的 onProgressUpdate() 方法中再次创建 mainactivity 类的实例。这就是为什么您在 textview 字段未启动时收到空指针异常的原因。

您的问题有一个简单的解决方案。 onProgressUpdate() 方法在主 UI 线程上运行,您可以访问 onProgressUpdate() 方法中的 textview 变量。所以只需执行以下操作:

@Override
protected void onProgressUpdate(String... values) 
    super.onProgressUpdate(values);
     MainActivity mainActivity =new MainActivity();

    for (String color : values) 

        textView.append(color + "\n");
    

【讨论】:

以上是关于如何从 android 中的 AsyncTask 获取 UI 参考的主要内容,如果未能解决你的问题,请参考以下文章

如何将变量从 AsyncTask 返回到 Android 中的 Google Map 活动

如何从android中的自定义适配器调用Activity asynctask

Android中的AsyncTask是如何执行的

从Android中的AsyncTask返回一个值[重复]

从Android中的AsyncTask返回一个值[重复]

在 Android 中,如何从 AsyncTask 更改 TextView? [复制]