2010-11-06 5 views
9

Ich entschuldige mich jetzt für den langen Post, aber das ist die einzige Art, wie ich erklären könnte, und Google gibt drei Seiten der Suchergebnisse, die nicht schlüssig sindAndroid Handler Nachricht und Listview

Hier ist mein Fehler Jungs:

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

Was ich versuche, ist eine Listenansicht, die von benutzerdefinierten Listenelementen gefüllt wird, jedes Listenelement hat mehrere Ansichten und jede Ansicht hat einen Onclick-Listener angeschlossen. Wenn dieser onClickListener gedrückt wird, sendet er eine Nachricht an einen Handler mit den Argumenten what und arg1. Durch Klicken auf eines meiner Elemente wird eine Absicht zum Starten einer neuen Aktivität ausgelöst. Klicken auf die andere zeigt einen Toast. Wenn diese in einer Kombination gedrückt werden, bekomme ich den Fehler oben. Nämlich klicken Sie auf den Text, um die Absicht zu feuern, (dann drücken Sie zurück) und klicken Sie dann auf das Bild, um den Toast zu zeigen, dann, wenn Sie den Text klicken, um die Absicht wieder zu feuern, bekomme ich den FC.

ich ein Demo-Projekt erstellt haben, die diese wiedergibt: http://rapidshare.com/files/429227042/HandlerTest.rar

Und hier ist der Code unten, habe ich versucht, so viel cruft zu entfernen, wie ich konnte, um die Knochen des Fehlers zu erhalten:

wenn Sie möchten, was wichtig Blick auf die OnClickListener die in ConversationAdapter.class überspringen und wie sie interagieren mit StartPage.class

Android Manifest:

<?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> 

Sorry für den gesamten Code!

Antwort

32

Meine Vermutung wäre, dass Sie zweimal die gleiche Nachricht senden. Tatsächlich gibt es im Code einen new Message() und zwei mHandler.sendMessage(m), die möglicherweise beide ausgeführt werden.

Versuchen Sie, eine neue Nachricht für jedes Mal, wenn Sie eine Nachricht senden.

Edited:

Message.obtain() vorzuziehen Message m = new Message() (weil sie verwendete Meldungen unter der Haube rezykliert)

In Ihrem Fall könnten Sie new.copyFrom(old) verwenden, wenn Sie eine Kopie der bestehenden Nachricht benötigen.

+0

Hmm das funktioniert, ich habe versucht, Ressourcen (ja eine winzige Menge) zu speichern, indem man nur eine pro Ansicht, anstatt einer immer wenn der onclick gedrückt wird. Ich kann sehen, wie ein Fehler geworfen würde, wenn beide ausgeführt werden. Aber mit der Layout-Ansicht kann ich nicht sehen, dass dies möglich ist, muss das Betriebssystem fehlen es ist sauber? Wie auch immer es jetzt funktioniert. Verschieben Sie die neue Nachricht() in onClick. Danke! – Blundell

+0

Ah großartig, nicht nein, danke! neue Nachricht() geändert in Message.obtain() – Blundell