我有一个looper的问题。我打电话给looper.prepare()
,做完之后一切正常。但是如果我旋转设备,我会在准备工作中得到一个例外。
07-12 16:40:09.760: E/activity(15809): java.lang.RuntimeException: Only one Looper may be created per thread
我正试图退出弯针,但它没有做任何事情。
这是我的AsyncTask:
@Override
protected String doInBackground(String... args) {
try{Looper.prepare(); //here start the exception
try {
URL url = new URL(link);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
utente.measure(0, 0);
bmImg = decodeSampledBitmapFromResource(is,(int) utente.getMeasuredWidth(), utente.getMeasuredHeight(), link);
if(bmImg!=null){
try{
getCroppedBitmap();
}catch(Exception e){
System.out.println(e);
}
}
}
catch (IOException e)
{
Log.e("lele", "errore qui");
e.printStackTrace();
}
Looper.myLooper().quit(); //do nothings
}catch(Exception e){
Log.e("canta tu", " "+e);
}
Looper.myLooper().quit(); //do nothings
return null;
}
@Override
protected void onPostExecute(String args) {
//Looper.myLooper().quit(); //generathed an error, main thread can't stop looper
if(bmImg!=null){
try{
utente.setImageBitmap(bmImg);
ellisse.setVisibility(View.VISIBLE);
}catch(Exception e){
Log.e("lele",""+e);
Log.e("lele","errore probabile out of bound");
}
}
else {
Toast.makeText(getApplicationContext(), "Modifica la foto da \"profilo\"", Toast.LENGTH_LONG).show();
}
想法?
答案 0 :(得分:16)
有两种情况需要考虑:
(1)你想要在应用程序的整个生命周期中生活的looper线程,并且不要强烈引用视图(甚至不是隐含的)
Quoting Google工程师Christopher Tate - 您可以将looper留在那里,直到您的应用程序被销毁,并且它会随之崩溃。你不必担心它。
“非常普遍地说,永远不要退出()你的looper线程。这种方法主要是出于历史和测试的原因。在Real Life™中,我建议你继续重复使用相同的looper线程。过程而不是创建/退出它们。“
我使用这样一个looper线程作为多用途HandlerThread,并且只要我想在主线程(UI)之外运行某些东西,就将Runnables发送给它。
(2)引用视图的looper线程
这个不符合Christopher Tate的建议,因为它会导致内存泄漏,例如,如果您旋转屏幕。
(你最好使处理程序线程静态并使用弱引用 - 你将返回选项#1)
要杀死它你必须退出循环。为此,您需要在该线程的上下文中运行quit命令
所以用msg.what创建一个带有一些int的消息,并在handleMessage中等待这个int,当它到达时 - 调用:
Looper myLooper = Looper.myLooper();
if (myLooper!=null) {
myLooper.quit();
}
不要忘记取消对视图和活动的所有引用。
将此杀戮信息从您的活动onDestroy()
答案 1 :(得分:3)
Looper.prepare()
将Looper
- 实例与调用它的线程相关联,但Looper.quit()
不会删除此关联(它只会停止消息调度机制)。因此,当您再次拨打Looper.prepare
时,会抛出RuntimeException
。
一般建议不要将Looper
- 实例与AsyncTask
- 主题相关联。 Looper
用于在线程之间传递消息,但这已在AsyncTask
内部处理,因此可以在onPreExecute
(UI线程) - >之间发送数据。 doInBackground
(工作人员主题) - > onPostExecute
(UI线程)。