Cómo administrar adaptadores personalizados onPause, onResume of Activity en Android
Tengo un adaptador usado para exhibir mensajes en la visión de la lista iguales mensajes en la aplicación de la charla. Puedo mostrar el contenido perfectamente una vez que la actividad se crea, pero cuando vuelvo y creo la actividad otra vez, el adaptador no trabaja como de costumbre.
Lo que encontré en la depuración es la siguiente:
- ListView.getCheckedItemPositions no puede devolver elementos marcados en SparseBooleanArray
- Android: ListView vertical con filas superpuestas
- ListView con disposición de filas personalizada - Android
- Detener la animación de desplazamiento ListView
- Elemento de vista de lista de Android que no muestra el color seleccionado
- Función recibe () se llama cuando se recibe el mensaje y actualizar el registro, como he mencionado anteriormente no hay ningún problema para mostrar los datos en la vista de lista una vez que la actividad se crea, pero una vez que volver y relauch la actividad no soy capaz de Mostrar los mensajes recibidos.
¿Hay algo que me falta en onResume () onPause o onStart () método con respecto al adaptador personalizado, como el registro o la decalificación del adaptador personalizado de nuevo? Gracias por la ayuda.
A continuación se muestra el código de mi clase de actividad que utiliza un adaptador personalizado para mostrar los mensajes enviados y recibidos:
public class hotListener extends ListActivity { private XMPPConnection connection; private IBinder binder; private Handler mHandler = new Handler(); private ArrayList<String> messages = new ArrayList<String>(); ArrayList<ChatMessage> messagex= new ArrayList<ChatMessage>();; ChattingAdapter adaptex; Intent mIntent ; private ListView listview; EditText sender_message ; String msg; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listener); //messagex.add(new ChatMessage("Hello", false)); adaptex = new ChattingAdapter(getApplicationContext(),messagex); setListAdapter(adaptex); Button send_button = (Button) findViewById(R.id.chat_send_message); sender_message = (EditText) findViewById(R.id.chat_input); send_button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { msg = sender_message.getText().toString(); sender_message.setText(""); if(!(msg.length()==0)){ messagex.add(new ChatMessage(msg, true)); //addNewMessage(new ChatMessage(msg, true)); adaptex.notifyDataSetChanged(); getListView().setSelection(messagex.size()-1); } } }); if(!isMyServiceRunning()){ System.out.println("seems like service not running"); startService(new Intent(this,xService.class)); System.out.print(" now started "); } } @Override protected void onStart(){ super.onStart(); Boolean kuch = bindService(new Intent(this,xService.class), mConnection,Context.BIND_AUTO_CREATE); //System.out.println(kuch); System.out.println("bind done"); } private void receives(XMPPConnection connection2) { //ChatManager chatmanager = connection.getChatManager(); connection2.getChatManager().addChatListener(new ChatManagerListener() { @Override public void chatCreated(Chat arg0, boolean arg1) { arg0.addMessageListener(new MessageListener() { @Override public void processMessage(Chat chat, Message message) { final String from = message.getFrom(); final String body = message.getBody(); mHandler.post(new Runnable() { ChatMessage kudi = new ChatMessage(body, false); @Override public void run() { messagex.add(kudi); adaptex.notifyDataSetChanged(); getListView().setSelection(messagex.size()-1); Toast.makeText(hotListener.this,body,Toast.LENGTH_SHORT).show(); } }); } }); } }); } private boolean isMyServiceRunning() { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for(RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)){ if(xService.class.getName().equals(service.service.getClassName())){ return true; } } //System.out.print("false"); return false; } @Override protected void onResume() { bindService(new Intent(this, xService.class), mConnection, Context.BIND_AUTO_CREATE); super.onResume(); } @Override protected void onPause() { unbindService(mConnection); super.onPause(); } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { connection = null; service = null; } @Override public void onServiceConnected(ComponentName name, IBinder binder) { //System.out.println("binding in hot listener"); service = ((xService.MyBinder)binder).getService(); connection = service.getConnection(); receives(connection); Log.wtf("Service","connected"); } }; void addNewMessage(ChatMessage m) { System.out.println("1"); messagex.add(m); System.out.println("2"); adaptex.notifyDataSetChanged(); System.out.println("3"); getListView().setSelection(messagex.size()-1); } }
Aquí está mi adaptador de encargo (no hay problema en el adaptador de encargo pero agregando para hacer las cosas claras):
public class ChattingAdapter extends BaseAdapter{ private Context mContext; private ArrayList<ChatMessage> mMessages; public ChattingAdapter(Context context, ArrayList<ChatMessage> messages) { super(); this.mContext = context; this.mMessages = messages; } @Override public int getCount() { return mMessages.size(); } @Override public Object getItem(int position) { return mMessages.get(position); } @Override public View getView(int position, View convertView, ViewGroup parent) { ChatMessage message = (ChatMessage) this.getItem(position); ViewHolder holder; if(convertView == null) { holder = new ViewHolder(); convertView = LayoutInflater.from(mContext).inflate(R.layout.listitem, parent, false); holder.message = (TextView) convertView.findViewById(R.id.text1); convertView.setTag(holder); } else holder = (ViewHolder) convertView.getTag(); holder.message.setText(message.getMessage()); LayoutParams lp = (LayoutParams) holder.message.getLayoutParams(); //Check whether message is mine to show green background and align to right if(message.isMine()) { holder.message.setBackgroundResource(R.drawable.msgbox_new_selected_go_up); lp.gravity = Gravity.RIGHT; } //If not mine then it is from sender to show orange background and align to left else { holder.message.setBackgroundResource(R.drawable.msgbox_other_go_up); lp.gravity = Gravity.LEFT; } holder.message.setLayoutParams(lp); //holder.message.setTextColor(R.color.textColor); return convertView; } private static class ViewHolder { TextView message; } @Override public long getItemId(int position) { //Unimplemented, because we aren't using Sqlite. return position; } }
Ps: No estoy almacenando ningún mensaje en sqlite ya que no quiero restaurar mensajes por ahora, pero quiero que se muestren nuevos mensajes por lo menos onresume de activty. Puedo mostrar los mensajes enviados después de presionar enviar botón pero no recibió mensajes que funciona bien para la primera vez que se crea la actividad.
EDIT: Hice más depuración, resulta que el problema no está en la actividad de reanudar, si no uso receive () función por primera vez, y reanudar la actividad después de volver, entonces recibe () funcionará, es decir, la función dentro recibe ): getListView().setSelection(messagex.size()-1);
Funciona una sola vez. Ya sea la primera vez en la recepción de mensajes o la próxima vez si y sólo si no se llama la primera vez en la actividad.
- Android ListView Seleccionar animación
- Obtener contacto Foto basada en Teléfono de contacto Android - Ejemplo de trabajo
- Adaptador personalizado getView () no se está utilizando la biblioteca PullToRefresh
- Vista de lista expandida necesaria para expandir la fila una a la vez
- ActionBar - PullToRefresh
- RequestLayout () incorrectamente llamado por android.widget.RelativeLayout android
- Eliminar ListView pie de página Click Listener
- ¿Cómo puedo mostrar contenido CSV específico en el elemento de la lista que se ha hecho clic?
Creo que el problema reside cuando se intenta reanudar la actividad, todavía está ejecutando el mHandler anterior en ejecución y por lo tanto su instancia de mensaje no se destruye y cuando se reanuda su actividad que crea un problema. Asegúrese de que su mhandler destruye toda instancia de objetos cuando se llama unstop.
No hay ningún lugar en el código donde guarde su messagex
ArrayList. Cuando abandones tu actividad golpeando hacia atrás, tu matriz se distroye (Garbage Collection se encarga de ello).
Cuando messagex
su actividad, su messagex
ArrayList se crea de nuevo, es una variable nueva.
De hecho, no estás relanzando tu actividad, estás creando una nueva instancia.
EDITAR:
Nunca he trabajado con los objetos XMPPConnection antes, pero algo que vale la pena probar es el siguiente:
Cuando se enlaza con el servicio, está llamando a connection2.getChatManager().addChatListener
y también arg0.addMessageListener
pero al desvincular no está llamando a ningún método removeXXX
. Podría ser que ya que no está eliminando a sus oyentes, todo el objeto XMPPConnection todavía tiene referencias a los oyentes que viven en una actividad muerta, y no están siendo recogidos basura.
En el código mencionado anteriormente, nunca ha actualizado ArrayList en su clase de adaptador personalizado después de reanudar la actividad o el mensaje de servicio obtener.
Solución:
Cambie su constructor de adaptador personalizado como, public ChattingAdapter(Context context)
y cree un método como se menciona a continuación
public void updateMessage(ArrayList<ChatMessage> messages) { this.mMessages.clear(); this.mMessages = messages; notifyDataSetChanged(); }
Y también en la clase adaptadora personalizada inicializar el mMessages
como new ArrayList<ChatMessage>();
En la declaración sí mismo de otra manera usted conseguirá la excepción del puntero nulo.
Y en su Activador hotListener, el método addNewMessage (ChatMessage m) debe cambiar como se menciona a continuación
void addNewMessage(ChatMessage m) { System.out.println("1"); messagex.add(m); System.out.println("2"); adaptex.updateMessage(messagex); //adaptex.notifyDataSetChanged(); System.out.println("3"); getListView().setSelection(messagex.size()-1); }
- Advertencias de gradol y roboguice 2.0 de Android
- El submenú de la barra de acciones no funciona después de que se invoca a supportInvalidateOptionsMenu