开发者

Thread remains in NEW state if started from AsyncTask by runOnUiThread

Here is an example application I wrote to reproduce the memory leak related issue i have met :

 package a.b.mapleak;
 import android.app.Activity;
 import android.content.Context;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 import android.widget.TextView;

public class MapLeak extends Activity
{
TextView callVoidText, getNewDataText, getDataStringText;
Button callVoidButton, getNewDataButton, getDataStringButton;
Handler callbackHandler;
MemoryLeak memleak;
private LoadAccountsTask mLoadAccountsTask = null;
private class LoadAccountsTask extends AsyncTask<Void, Void, Object[]> {

    private int mCursor1;
    private int mCursor2;
    private Context context;
    private UITask t = new UITask();


    @Override
    protected Object[] doInBackground(Void... params) {

        runOnUiThre开发者_开发知识库ad(t);

        // Create the summaries cursor
        mCursor1 = 1;
        mCursor2 = 2;
        return new Object[] { mCursor1, mCursor2};
    };
  private class UITask extends Thread {
        @Override
        public void run() {
            int i = 2;
            while (i>0) {
                i--;
            }
            Thread.State state=t.getState();
            Log.e(ALARM_SERVICE, "Thread state in run is " + state.toString());

        }
    }

}


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    getDataStringText = (TextView) findViewById(R.id.getDataString_text);
    getDataStringButton = (Button) findViewById(R.id.getDataString_button);
    getDataStringButton.setOnClickListener(new Button.OnClickListener() {
        long i = 0;
        public void onClick(View v) {
           if (mLoadAccountsTask != null) mLoadAccountsTask.cancel(true);
           mLoadAccountsTask = (LoadAccountsTask) new LoadAccountsTask(this).execute();
        }
    });

}

}

I found that the thread started in runOnUiThread has never been exited. For some unknown to me reason the task was running, but the output from

Log.e(ALARM_SERVICE, "Thread state in run is " + state.toString());

every time was "Thread state in run is NEW" e.g. ''The thread has been created, but has never been started.''. So the thread was running continuously preventing "LoadAccountsTask" class from being garbage collected. Thus, in this example, every time the button is pressed - the new "LoadAccountsTask" appeared in memory.

But, if to replace

private class UITask extends Thread 

with

private class UITask implements Run

there was no memory leak, the thread exited successfully. Of course state=t.getState(); will not work in this case and should be commented.

Do anybody have an explanation why it is so?


Focusing on your immediate concern, runOnUiThread() takes a Runnable. While Thread does implement Runnable, runOnUiThread() will not treat it as a Thread. Please just pass a Runnable to runOnUiThread().

Second, never call runOnUiThread() from doInBackground(). Just perform the work from that Runnable in onPreExecute() or onPostExecute(), which are executed on the main application thread.

Third, if you ever do write a real Thread, don't busy-loop in it.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜