Поток остается в новом состоянии, если запущен из AsyncTask runOnUiThread - PullRequest
0 голосов
/ 08 июня 2011

Вот пример приложения, которое я написал для воспроизведения проблемы утечки памяти, с которой я столкнулся:

 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) {

        runOnUiThread(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();
        }
    });

}

}

Я обнаружил, что поток, начатый в runOnUiThread, никогда не завершался. По какой-то неизвестной мне причине задача была запущена, но вывод

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

каждый раз, когда было указано "Состояние потока в состоянии выполнения НОВОЕ", например '' Тема создана, но никогда не запускалась. '' Таким образом, поток работал непрерывно, предотвращая сборку мусора классом «LoadAccountsTask». Таким образом, в этом примере каждый раз, когда нажимается кнопка - в памяти появляется новый «LoadAccountsTask».

Но, если заменить

private class UITask extends Thread 

с

private class UITask implements Run

утечки памяти не было, поток успешно завершен. Конечно, состояние = t.getState (); не будет работать в этом случае и должен быть прокомментирован.

У кого-нибудь есть объяснение, почему это так?

1 Ответ

0 голосов
/ 08 июня 2011

Сосредоточив внимание на вашей непосредственной заботе, runOnUiThread() занимает Runnable.Хотя Thread реализует Runnable, runOnUiThread() не будет воспринимать его как Thread.Пожалуйста, просто передайте Runnable на runOnUiThread().

Во-вторых, никогда не звоните runOnUiThread() с doInBackground().Просто выполните работу с этими Runnable в onPreExecute() или onPostExecute(), которые выполняются в главном потоке приложения.

В-третьих, если вы когда-нибудь напишите реальный Thread, не занимайтесьв ней.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...