开发者

Running same background task from two activities

In my app I have a background task (using AsyncTask) that downloads stuff from a web site.

This task can be called from two separate activities, and it is possible to call it twice. So in "activity1" the background task "update" is called, and runs for a while (it takes something like 5-10 seconds usually). Then while it's running, user switches to "activity2" and runs "update" again. This gives problems: either a crash when both try to clear the database (command: DELETE FROM table) at the same time, causing a "database locked" error. Or they try to put the same item in the database causing a duplicate.

I've tried to solve this by setting a static boolean flag to true when a task is active. When the task is called, it will check for this flag, and if true (i.e. the same task running on another thread) it goes into a wait loop using a handler until this flag clears, and then returns. This to make sure that when the background task returns, the update has been done. I have to use a Looper for that: this sometimes fails with an error "can create only one looper per thread". And I really have it in a way that only one looper can be started, this is the offending code, which appears at the start of the background task:

    if (active) {
        Looper.prepare();
        handler = new Handler();
        handler.postDelayed(new Runnable() {
            int count = 0;

            @Override
            public void run() {
                if (active) {
                    count++;
                    if (count < 1000) 
                        h开发者_StackOverflow社区andler.postDelayed(this, 100);
                }
            }
        }, 100);
        Looper.loop();
        active = false;
        return "done";
    }

And to make matters worse it often seems to hang in this loop, without returning.

How to solve such a situation?


Why don't use synchronization instead? It sounds like a concurrency issue. Why don't you make sure that if the first background task is running then the second background task is sleeping until the first one is finished.

Or ensure somehow, that if the user switches to Activity number 2, the background task from activity number 1 is cancelled.


Instead of the AsyncTask you can consider to use IntentService. Have a look at the Android Service concept. The IntentService class ensures that only one request will be processed at one time.

I found this answer very useful during implementing IntentService with Activity callback communication.


Database locking issues solved by wrapping it into a ContentProvider. Besides problems with a method being called again before the previous instance was finished, I had the issue of different methods running in different background threads clashing while trying to write to the database.

Officially designed to allow for sharing data between apps, it also works great for sharing data between threads in a single app. The ContentProvider will make sure that no locking issues occur.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜