2010-11-06 16 views
9

przepraszam teraz za długi post, ale jest to jedyny sposób mogę wytłumaczyć, a Google daje 3 stron wyników, które nie są rozstrzygająceAndroid Handler wiadomość i ListView

Oto moi ludzie o błędach:

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

Próbuję mieć widok listy, który jest zapełniany niestandardowymi elementami listy, każdy element listy ma wiele widoków, a każdy widok ma dołączony odbiornik onclick. Po naciśnięciu tego przycisku onClickListener wysyła komunikat do programu obsługi z argumentami what i arg1. Kliknięcie jednego z moich elementów wywołuje zamiar rozpoczęcia nowej aktywności. Kliknięcie drugiego pokazuje toast. Po naciśnięciu kombinacji otrzymam powyższy błąd. Mianowicie klikając tekst, aby wystrzelić intencję, (następnie naciśnij), a następnie klikając obraz, aby wyświetlić toast, a następnie po kliknięciu tekstu, aby ponownie uruchomić cel, otrzymuję FC.

Stworzyłem projekt demo, który reprodukuje to: http://rapidshare.com/files/429227042/HandlerTest.rar

A oto kod poniżej, starałem się usunąć jak najwięcej cruft jak mogłem dostać się do kości błędu:

Jeśli chcesz przejść do co ważne spojrzenie na onClickListener jest w ConversationAdapter.class i jak współdziałają one ze StartPage.class

Android manifeście:

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

Niestety dla wszystkich kodu!

Odpowiedz

32

Domyślam się, że wysyłasz dwa razy tę samą wiadomość. Rzeczywiście w kodzie znajduje się jeden new Message() i dwa mHandler.sendMessage(m), które są prawdopodobnie oba wykonywane.

Spróbuj utworzyć nową wiadomość za każdym razem, gdy wysyłasz wiadomość.

Zmieniano:

Message.obtain() korzystne jest Message m = new Message() (ponieważ przetwarza używane wiadomości pod maską)

W twoim przypadku można wykorzystać new.copyFrom(old) jeśli potrzebujesz kopię istniejącej wiadomości.

+0

Hmm, to działa, próbowałem zaoszczędzić zasoby (tak, niewielka ilość), po prostu mając jeden na widok, zamiast jednego za każdym razem, gdy naciśnięto przycisk onclick. Widzę, jak zostałby zgłoszony błąd, jeśli oba zostaną sprawdzone. Ale w widoku układu nie widzę, aby było to możliwe, ale w systemie operacyjnym ht musi być wyczyszczony? Tak czy inaczej to teraz działa. Przenosząc nową wiadomość() do onClick. Dzięki! – Blundell

+0

Ah wielki nie, nie, dzięki! nowa wiadomość() zmieniona na Message.obtain() – Blundell