如果父 Activity finish(),Activity 类作用域字段变量是否可以在 AsyncTask 中访问

发布于 2024-12-03 22:19:53 字数 794 浏览 0 评论 0原文

进行一些测试但无法构建调试环境
所以也许有人可以回答这个问题。

在我的 Activity 中,我启动了一个 AsyncTask
这个AsyncTask正在写入Sqlite并且需要很长时间。

我以为我可以在用户按下“发送”按钮时启动 AsyncTask
然后点击后退按钮来finish()该活动。

我知道即使 Activityfinish() 正确,AsyncTask 也会继续运行。

问题是如何让田地保持活力?

如果父 finish() 的话,此代码中的 localArrayPeople 会发生什么情况?

private class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> 
{
    ArrayList localArrayPeople;

    @Override
    protected Integer doInBackground(Long... params) {

        this.localArrayPeople =  arrayPeople;

        // Do stuff...
    }
}

我知道我可以/应该使用服务,但要发送到服务的数据/对象量服务
真的很多。
我知道这是一个坏主意,所以出于教育目的,请回答问题,不要警告我

Doing some testing but cannot fabricate debug environment
so maybe someone can answer this.

In my Activity i start an AsyncTask.
This AsyncTask is writing to Sqlite and it take long time.

I thought i could start the AsyncTask when user press the "Send" Button
and then hit the back button to finish() the Activity.

I know AsyncTask will keep on running even do Activity is finish() right.

The question is how do keep the fields alive?

What happen with the localArrayPeople in this code if parent finish()?

private class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> 
{
    ArrayList localArrayPeople;

    @Override
    protected Integer doInBackground(Long... params) {

        this.localArrayPeople =  arrayPeople;

        // Do stuff...
    }
}

I know i can/should use a Service but the amount of data/Object's to send to the Service
is really much.
I know this is a bad ide so please for education purpose just answer the question and dont warn me

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ぽ尐不点ル 2024-12-10 22:19:53

回答你的问题。 java 程序中的对象永远不会“消失”,因此字段不会丢失引用,例如突然开始指向 null。仅当没有人引用对象时,GC 才会删除对象。

在您的情况下,当 Activity 停止时,后台线程中的字段不会受到影响。

唯一的问题可能是 Android 操作系统决定从内存中删除您的应用程序并杀死其所有线程。如果您有一个长时间运行的后台线程并且您的应用程序处于非活动状态(= 活动未显示),则可能会发生这种情况。

To answer yor question. Objects in java programs never just "go away", so fields don't loose references, e.g. suddenly start pointing to null. Objects are only removed by GC when nobody references them.

In your case, when Activity stops, the fields in background thread will not be affected.

The only problem could be that Android OS decides to remove your app from memory and kills all it's threads. This can happen if you have a really long running background thread and your app is inactive (= activity not showing).

哥,最终变帅啦 2024-12-10 22:19:53

回答您原来的问题:+1 给@PeterKnego 答案。

回答你最后的评论“我应该做什么,完成后使 localArrayPeople=null?”:不,你的 AsyncTask 保存对 Activity 的引用,因为每个内部类都保存对其外部类的引用(通过隐藏的 this $0 字段)。

正如我在评论中提到的文章中所述(“避免内存泄漏”):

如果您不控制,请避免在活动中使用非静态内部类
他们的生命周期,使用静态内部类并进行弱引用
到里面的活动。

因此,使您的 AsyncTaskDoStuff 类成为一个静态内部类:

private static class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> 

如果您需要在 AsyncTask 中使用 Context 对象,请将应用程序上下文传递给 AsyncTaskDoStuff 构造函数:

private static class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> {

   private final Context context;

   AsyncTaskDoStuff(Context context) {
     this.context = context;
   }

}

// in the activity:
AsyncTaskDoStuff async = new AsyncTaskDoStuff(getApplicationContext());

如果您需要读取某些 Activity 字段,则同样适用,通过 AsyncTaskDoStuff 构造函数(或通过其 execute 方法)传递它们。

如果需要修改 AsyncTask.doInBackground 方法中的 Activity 字段,请执行以下操作:

private static class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> {

   private final WeakReference<MyActivity> ref;

   AsyncTaskDoStuff(MyActivity activity) {
     this.ref = new WeakReference<MyActivity>(activity);
   }

   @Override
   protected Integer doInBackground(Long... params) {       
     MyActivity activity = ref.get();
     if (activity != null) {
       // access activity fields here
       activity.someField = ...
       ...
     } else {
       // activity object was already destroyed
     }
   }
}

// make sure accessed field is declared as volatile in the Activity
private volatile int someField;

Answering your original question: +1 to @PeterKnego answer.

Answering your last comment "What should i do, Make the localArrayPeople=null when im done?": No, your AsyncTask holds the reference to the Activity as every inner class holds a reference to its outer class (through the hidden this$0 field).

As stated in the article I referred in my comment ("Avoiding memory leaks"):

Avoid non-static inner classes in an activity if you don't control
their life cycle, use a static inner class and make a weak reference
to the activity inside.

Thus make your AsyncTaskDoStuff class a static inner one:

private static class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> 

If you need to use a Context object in the AsyncTask, pass the application context to AsyncTaskDoStuff constructor:

private static class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> {

   private final Context context;

   AsyncTaskDoStuff(Context context) {
     this.context = context;
   }

}

// in the activity:
AsyncTaskDoStuff async = new AsyncTaskDoStuff(getApplicationContext());

The same applies if you need to read some of the Activity fields, pass them through the AsyncTaskDoStuff constructor (or through its execute method).

If you need to modify Activity fields in the AsyncTask.doInBackground method do the following:

private static class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> {

   private final WeakReference<MyActivity> ref;

   AsyncTaskDoStuff(MyActivity activity) {
     this.ref = new WeakReference<MyActivity>(activity);
   }

   @Override
   protected Integer doInBackground(Long... params) {       
     MyActivity activity = ref.get();
     if (activity != null) {
       // access activity fields here
       activity.someField = ...
       ...
     } else {
       // activity object was already destroyed
     }
   }
}

// make sure accessed field is declared as volatile in the Activity
private volatile int someField;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文