1

我在上一个问题中遇到问题,我不确定我的代码是否存在内存泄漏。一些答案与它在 UI 线程上运行并因此阻塞有关。是的,它在 UI 线程上运行并且不会产生新线程。

所以为了解决这个问题,我使用Thread而不是Handler在 UI 之外生成一个新线程。现在的问题是我无法像在 UI 线程中运行的那样延迟它。

这是我之前的问题,我的原始 UI 线程代码是:这个 Runnable 是否可以避免内存泄漏?以下是生成新线程的更新代码:

package com.example.helloworld;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
import android.util.Log;
import java.lang.ref.WeakReference;

public class HelloWorldActivity extends Activity
{

    private static TextView txtview;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        txtview = (TextView) findViewById(R.id.mainview);

        Thread t = new Thread(new WeakRunnable(txtview));
        t.start();
    }

    private static final class WeakRunnable implements Runnable {
        private final WeakReference<TextView> mtextview;

        protected WeakRunnable(TextView textview){
            mtextview = new WeakReference<TextView>(textview);
        }

            @Override
            public void run() {
                TextView textview = mtextview.get();
                if (textview != null) {

                    try {
                        Thread.sleep(1500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    int test = 5*5;
                    txtview.setText("Hola Mundo"+test);
                }
                Log.d("com.example.helloworld", "" + Thread.currentThread().getName()); // Outputs "Thread-<num>" if not running on UI thread
            }
    }           

}

它只是设置视图文本并附加5*5.

一旦我启动应用程序,它就会自行退出,我不明白为什么。有些东西告诉我我以错误的方式延迟它或使用runOnUiThread错误。即使更改txtview.setText("Hola Mundo"+test);runOnUiThread( txtview.setText("Hola Mundo"+test) );不会编译给出错误:'void' type not allowed here.

简而言之:计算(5*5在这种情况下)应该在单独的线程上完成以避免阻塞主(UI)线程,并且应该在 UI 上设置文本,从单独的线程中获取计算项。您自己的一个简单示例也可以。

更新 我已经发布了我自己的问题实施的答案AsyncTask

4

3 回答 3

2

使用Handler类和Views中的 postDelayed 方法

改变,

    Thread t = new Thread(new WeakRunnable(txtview));
    t.start();

至 :

    txtview.postDelayed(new WeakRunnable(txtview), 1500);

然后删除 runnable 中的以下 sleep 子句,因为它不再需要

                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
于 2015-04-17T15:27:09.800 回答
1

您可以使用条件直到满足,而不是使用 thread.sleep();

 Condition.wait(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                return textview != null;
            }
        });
于 2015-04-17T15:27:02.927 回答
1

正如@Axxiss 所说,这种情况更适合AsyncTask. 我更新了我的代码以使用AsyncTaskaWeakReference以避免内存泄漏:

package com.example.helloworld;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.AsyncTask;
import android.widget.TextView;
import android.util.Log;
import java.lang.ref.WeakReference;

public class HelloWorldActivity extends Activity
{

    private static TextView txtview;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        txtview = (TextView) findViewById(R.id.mainview);

        SimpleTask objSimpleTask=new SimpleTask();
        objSimpleTask.execute();
    }

    private static class SimpleTask extends AsyncTask<Void,Void,String> {
        private WeakReference<TextView> mtextview = new WeakReference<TextView>(txtview);

        @Override
        protected String doInBackground(Void... params) {
            Log.d("com.example.helloworld", "" + Thread.currentThread().getName());
            try{
                Thread.sleep(1500);
            } catch(InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
            return "Hola Mundo";
        }
        @Override
        protected void onPostExecute(String result) {
            TextView mtxtview = mtextview.get();
            mtxtview.setText(result);
        }


    }           

}

doInBackground在单独的线程中执行代码,而您稍后可以捕获结果onPostExecute并在主(UI)线程中执行它而无需任何装饰。

于 2015-04-17T22:08:14.250 回答