2010-11-06 18 views
9

me disculpo ahora para el puesto de largo, pero esta es la única manera de que pudiera explicar, y Google le da 3 páginas de resultados que no son concluyentesAndroid controlador de mensajes y ListView

Aquí está mi chicos de error:

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

Lo que intento es tener una vista de lista, que esté llena de elementos de lista personalizados, cada elemento de lista tiene varias vistas y cada vista tiene un oyente onclick adjunto. Cuando se presiona onClickListener envía un mensaje a un controlador con argumentos what y arg1. Al hacer clic en uno de mis elementos se activa una intención para comenzar una nueva actividad. Al hacer clic en el otro muestra un brindis. Cuando se presionan en una combinación, aparece el error anterior. A saber, hacer clic en el texto para disparar el intento, (luego presionar hacia atrás) y luego hacer clic en la imagen para mostrar el brindis, luego, cuando haces clic en el texto para disparar la intención nuevamente, obtengo el FC.

He creado un proyecto de demostración que reproduce la siguiente: http://rapidshare.com/files/429227042/HandlerTest.rar

Y aquí está por debajo del código, he tratado de eliminar la mayor cantidad costra que pude llegar a los huesos del error:

Si desea saltar a ver cuál es importante en la OnClickListener de en ConversationAdapter.class y cómo interactúan con StartPage.class

Android Manifiesto:

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

Lo siento por todo el código!

Respuesta

32

Supongo que enviarás dos veces el mismo mensaje. De hecho, en el código hay uno new Message() y dos mHandler.sendMessage(m) que posiblemente se hayan ejecutado.

Intente hacer un nuevo mensaje para cada vez que envíe un mensaje.

Editado:

Message.obtain() es preferible Message m = new Message() (ya que recicla los mensajes en inglés, bajo el capó)

En su caso, usted podría utilizar new.copyFrom(old) si necesita una copia del mensaje existente.

+0

Hmm esto sí funciona, estaba tratando de ahorrar recursos (sí, una cantidad minúscula) con solo tener uno por vista, en lugar de uno cada vez que se presiona el botón onclick. Puedo ver cómo se lanzará un error si ambos se ejecutan. Pero con la vista de diseño no puedo ver que esto sea posible, ¿debe faltar el sistema operativo? ¿Está limpio? De cualquier forma, ahora está funcionando. Al mover el nuevo mensaje() al onClick. Gracias! – Blundell

+0

¡Ah, genial! No, no, gracias. nuevo mensaje() cambiado a Message.obtain() – Blundell