如果在UI线程上运行Runnable不是一个选项,如何延迟生成的线程?
我之前的问题有问题,我不确定我的代码是否有内存泄漏。 一些答案涉及它在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 mtextview; protected WeakRunnable(TextView textview){ mtextview = new WeakReference(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-" if not running on UI thread } } }
它只是设置视图文本并附加5*5
的结果。
一旦我启动应用程序它退出自己,我不明白为什么。 有些东西告诉我,我以错误的方式推迟它或使用runOnUiThread
错误。 甚至改变txtview.setText("Hola Mundo"+test);
to runOnUiThread( txtview.setText("Hola Mundo"+test) );
没有编译给出错误: 'void' type not allowed here
。
简而言之:计算(在这种情况下为5*5
)应该在一个单独的线程上完成,以避免阻塞主(UI)线程,并且应该在UI上设置文本,从单独的线程中获取计算项。 你自己的一个简单例子也可以。
更新我已经发布了我自己的问题实现AsyncTask
的答案。
您可以使用条件直到满足它而不是使用thread.sleep();
Condition.wait(new Callable() { @Override public Boolean call() throws Exception { return textview != null; } });
使用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(); }
正如@Axxiss所说,这种情况更适合AsyncTask
。 我更新了我的代码以使用带有WeakReference
AsyncTask
来避免内存泄漏:
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 { private WeakReference mtextview = new WeakReference (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)线程中执行它而不需要任何装饰。