首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当UI线程上的可运行运行不是选项时,如何延迟生成的线程?

当UI线程上的可运行运行不是选项时,如何延迟生成的线程?
EN

Stack Overflow用户
提问于 2015-04-17 15:19:08
回答 3查看 787关注 0票数 1

我不确定我的代码是否有内存泄漏,这与之前的一个问题有问题。有几个答案与它在UI线程上运行和阻塞有关。这是真的,它运行在UI线程上,不产生新的线程。

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

这是我前面的问题,我最初的UI线程代码是:这是安全运行的内存泄漏吗?,下面是生成新线程的更新代码:

代码语言:javascript
复制
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的问题的答案。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-04-17 15:27:02

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

代码语言:javascript
复制
 Condition.wait(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                return textview != null;
            }
        });
票数 1
EN

Stack Overflow用户

发布于 2015-04-17 15:27:09

使用在postDelayed类和视图中找到的视图方法

变化,

代码语言:javascript
复制
    Thread t = new Thread(new WeakRunnable(txtview));
    t.start();

致:

代码语言:javascript
复制
    txtview.postDelayed(new WeakRunnable(txtview), 1500);

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

代码语言:javascript
复制
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
票数 2
EN

Stack Overflow用户

发布于 2015-04-17 22:08:14

正如@Axxiss所说,这个案子更适合AsyncTask。为了避免内存泄漏,我更新了代码以使用AsyncTaskWeakReference

代码语言:javascript
复制
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)线程中执行它,而不需要任何修饰。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29703226

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档