当前位置: 首页 > 知识库问答 >
问题:

警告:此AsyncTask类应该是静态的,否则可能发生泄漏

燕禄
2023-03-14

这是我的代码:

 new AsyncTask<Void,Void,Void>(){

        @Override
        protected Void doInBackground(Void... params) {
            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    mAdapter.notifyDataSetChanged();
                }
            });

            return null;
        }
    }.execute();

我怎么纠正这个?

共有1个答案

严正诚
2023-03-14

为了防止泄漏,可以使内部类保持静态。但是,这样做的问题是,您不再能够访问活动的UI视图或成员变量。您可以传入对上下文的引用,但这样做也会面临内存泄漏的风险。(如果AsyncTask类对活动有很强的引用,Android就不能在活动关闭后对其进行垃圾回收。)解决方案是对活动(或您需要的任何上下文)进行弱引用。

public class MyActivity extends AppCompatActivity {

    int mSomeMemberVariable = 123;

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

        // start the AsyncTask, passing the Activity context
        // in to a custom constructor 
        new MyTask(this).execute();
    }

    private static class MyTask extends AsyncTask<Void, Void, String> {

        private WeakReference<MyActivity> activityReference;

        // only retain a weak reference to the activity 
        MyTask(MyActivity context) {
            activityReference = new WeakReference<>(context);
        }

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

            // do some long running task...

            return "task finished";
        }

        @Override
        protected void onPostExecute(String result) {

            // get a reference to the activity if it is still there
            MyActivity activity = activityReference.get();
            if (activity == null || activity.isFinishing()) return;

            // modify the activity's UI
            TextView textView = activity.findViewById(R.id.textview);
            textView.setText(result);

            // access Activity member variables
            activity.mSomeMemberVariable = 321;
        }
    }
}

>

  • 据我所知,这种类型的内存泄漏危险一直是真的,但我只是在Android Studio3.0中才开始看到警告。许多主要的AsyncTask教程仍然没有涉及它(请参阅这里、这里、这里和这里)。
  • 如果AsyncTask是顶级类,也可以遵循类似的过程。静态内部类与Java中的顶级类基本相同。
  • 如果不需要活动本身,但仍然需要上下文(例如,要显示toast),可以传入对应用程序上下文的引用。在本例中,AsyncTask构造函数如下所示:

    private WeakReference<Application> appReference;
    
    MyTask(Application context) {
        appReference = new WeakReference<>(context);
    }
    

    在Kotlin中,不要包含内部类的inner关键字。这使得默认情况下它是静态的。

    class MyActivity : AppCompatActivity() {
    
        internal var mSomeMemberVariable = 123
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            // start the AsyncTask, passing the Activity context
            // in to a custom constructor
            MyTask(this).execute()
        }
    
        private class MyTask
        internal constructor(context: MyActivity) : AsyncTask<Void, Void, String>() {
    
            private val activityReference: WeakReference<MyActivity> = WeakReference(context)
    
            override fun doInBackground(vararg params: Void): String {
    
                // do some long running task...
    
                return "task finished"
            }
    
            override fun onPostExecute(result: String) {
    
                // get a reference to the activity if it is still there
                val activity = activityReference.get()
                if (activity == null || activity.isFinishing) return
    
                // modify the activity's UI
                val textView = activity.findViewById(R.id.textview)
                textView.setText(result)
    
                // access Activity member variables
                activity.mSomeMemberVariable = 321
            }
        }
    }
    

  •  类似资料: