我现在对于LONG的帖子表示歉意,但这是我唯一可以解释的方法,而google提供了3页结果并不是决定性的
这是我的错误家伙:
*** Uncaught remote exception! (Exceptions are not yet supported across processes.) android.util.AndroidRuntimeException: { what=1008 when=368280372 } This message is already in use. at android.os.MessageQueue.enqueueMessage(MessageQueue.java:171) at android.os.Handler.sendMessageAtTime(Handler.java:457) at android.os.Handler.sendMessageDelayed(Handler.java:430) at android.os.Handler.sendMessage(Handler.java:367) at android.view.ViewRoot.dispatchAppVisibility(ViewRoot.java:2748)
我正在尝试的是一个列表视图,由自定义列表项填充,每个列表项有多个视图,每个视图都附加了一个onclick侦听器.当这个onClickListener被按下时,它会向一个处理程序发送一个带有what和arg1参数的消息.
单击我的一个元素将触发启动新活动的意图.
点击另一个显示吐司.
当这些被组合按下时,我得到上面的错误.即点击文字来触发意图(然后按回车),然后点击图像显示吐司,然后当您点击文字再次触发意图时,我会得到FC.
我创建了一个演示项目,再现这个:
http://rapidshare.com/files/429227042/HandlerTest.rar
这里是下面的代码,我试图删除尽可能多的cruft,我可以得到的错误的骨头:
如果你想跳过什么重要的看看onClickListener在ConversationAdapter.class和他们如何与StartPage.class
Android清单:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.handler.test" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".StartPage" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".DetailsPage" android:label="DetailsPage" > </activity> </application> <uses-sdk android:minSdkVersion="3" /> </manifest>
StartPage.class:
package com.handler.test; import java.util.ArrayList; import android.app.ListActivity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.widget.Toast; public class StartPage extends ListActivity { private ArrayList<Conversation> mConversations = null; private ConversationAdapter mAdapter; private Context mContext; private ProgressDialog mProgressDialog; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mContext = this; mConversations = new ArrayList<Conversation>(); this.mAdapter = new ConversationAdapter(mContext,R.layout.inBox_row,mConversations,mHandler); setListAdapter(this.mAdapter); new Thread(new Runnable() { @Override public void run() { getConversations(); } }).start(); mProgressDialog = ProgressDialog.show(StartPage.this,"Please wait...","Retrieving data ...",true); } private void getConversations() { try { mConversations = new ArrayList<Conversation>(); Conversation o1 = new Conversation(); o1.setStatus("SF services"); o1.setMessage("Pending"); mConversations.add(o1); } catch (Exception e) { Log.e("BACKGROUND_PROC",e.getMessage()); } runOnUiThread(returnRes); } private Runnable returnRes = new Runnable() { @Override public void run() { if(mConversations != null && mConversations.size() > 0){ mAdapter.notifyDataSetChanged(); for(int i=0;i<mConversations.size();i++) mAdapter.add(mConversations.get(i)); } mProgressDialog.dismiss(); mAdapter.notifyDataSetChanged(); } }; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { int convIndex = msg.arg1; int viewTouched = msg.what; switch(viewTouched){ case ConversationAdapter.PROF_ICON: showNumber(convIndex); break; case ConversationAdapter.MESSAGE: showMessageDetails(convIndex); break; } super.handleMessage(msg); } }; private void showNumber(int convIndex) { Toast.makeText(mContext,"Pressed: "+convIndex,Toast.LENGTH_LONG).show(); } private void showMessageDetails(int convIndex) { final Conversation conv = mConversations.get(convIndex); Intent i = new Intent(mContext,DetailsPage.class); i.putExtra("someExtra",conv); startActivity(i); } }
DetailsPage.class
package com.handler.test; import android.app.Activity; import android.os.Bundle; import android.util.Log; public class DetailsPage extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Log.i("Test","Details Page"); } }
Conversation.class:
package com.handler.test; import java.io.Serializable; public class Conversation implements Serializable { private static final long serialVersionUID = -437261671361122258L; private String status; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } }
ConversationAdapter.class:
package com.handler.test; import java.util.ArrayList; import android.content.Context; import android.os.Handler; import android.os.Message; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.LinearLayout; public class ConversationAdapter extends ArrayAdapter<Conversation> { public static final int PROF_ICON = 0; public static final int MESSAGE = 1; private Context mContext; private Handler mHandler; private ArrayList<Conversation> mItems; private int mXmlId; private LinearLayout detailsOfConv; private ImageView iconImage; public ConversationAdapter(Context context,int textViewResourceId,ArrayList<Conversation> items,Handler handler) { super(context,textViewResourceId,items); this.mContext = context; this.mItems = items; this.mXmlId = textViewResourceId; this.mHandler = handler; } @Override public View getView(int position,View convertView,ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(mXmlId,null); } final Message m = new Message(); m.arg1 = position; Conversation c = mItems.get(position); if (c != null) { iconImage = (ImageView) v.findViewById(R.id.icon); if (iconImage != null) { iconImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { m.what = PROF_ICON; mHandler.sendMessage(m); } }); } detailsOfConv = (LinearLayout) v.findViewById(R.id.details); if(detailsOfConv != null){ detailsOfConv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { m.what = MESSAGE; mHandler.sendMessage(m); } }); } } return v; } }
main.xml中:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dip" > <ListView android:id="@+id/android:list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:cacheColorHint="#00000000" /> </LinearLayout>
inBox_row.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:padding="6dip"> <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_marginRight="6dip" android:src="@drawable/icon" /> <LinearLayout android:id="@+id/details" android:orientation="vertical" android:layout_width="0dip" android:layout_weight="1" android:layout_height="fill_parent"> <TextView android:id="@+id/toptext" android:textColor="#99FF66" android:layout_width="fill_parent" android:layout_height="0dip" android:layout_weight="1" android:singleLine="true" android:text="123456789" /> </LinearLayout> </LinearLayout>
对不起,所有的代码!
解决方法
我的猜测是,你发送两次相同的信息.实际上在代码中有一个新的Message()和两个mHandler.sendMessage(m)可能都被执行.
尝试在每次发送消息时发出新消息.
编辑:
Message.obtain()比Message m = new Message()更好(因为它回收了使用过的消息)
在您的情况下,如果需要现有消息的副本,则可以使用new.copyFrom(old).