【问题标题】:Android Handler Message and ListViewAndroid Handler 消息和 ListView
【发布时间】:2019-01-14 19:33:21
【问题描述】:

这是我的错误:

*** 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。

这是下面的代码,我试图尽可能多地删除错误的内容:

如果您想跳到重要的内容,请查看 ConversationAdapter.class 中的 onClickListener 以及它们如何与 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>

【问题讨论】:

    标签: android listview message-queue message handler


    【解决方案1】:

    我的猜测是您发送了两次相同的消息。实际上,代码中有一个new Message() 和两个mHandler.sendMessage(m),它们可能都被执行了。

    尝试在每次发送消息时创建一条新消息。

    已编辑:

    Message.obtain() 优于 Message m = new Message()(因为它在后台回收使用过的消息)

    如果您需要现有消息的副本,您可以使用new.copyFrom(old)

    【讨论】:

    • 嗯,这确实有效,我试图通过每个视图只有一个来节省资源(是的,数量很少),而不是每次按下 onclick 时都有一个。我可以看到如果两者都被执行,将如何引发错误。但是对于布局视图,我看不到这是可能的,ht OS 一定是缺少它的清理吗?无论哪种方式,它现在都在工作。通过将新的 Message() 移动到 onClick 中。谢谢!
    • 啊,太好了,没有,谢谢! new Message() 改为 Message.obtain()
    猜你喜欢
    • 1970-01-01
    • 2018-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 2012-12-11
    相关资源
    最近更新 更多