5

我有一个适配器,用于在列表视图中显示聊天应用程序中的消息。一旦创建活动,我就能够完美地显示内容,但当我再次返回并创建活动时,适配器不能正常工作。如何管理自定义适配器onPause,onResume of Android Android

我在调试发现是如下:

  • 功能接收()被接收到的消息时被调用,并更新 寄存器,正如我上面提到没有显示在列表视图中的 数据问题一旦创建活动,但一旦我回去 并重新启动活动,我无法显示收到的消息。

onResume()onPause或onStart()方法中是否存在与自定义适配器相关的问题,例如重新注册或转发自定义适配器?感谢帮助。

以下是我的活动类的,它使用自定义适配器来显示发送和接收消息的代码:

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); 
     } 
} 

这里是我的自定义适配器(存在自定义适配器没有问题,但增加了把事情说清楚) :

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:我不存储任何消息在SQLite作为我不想现在恢复的消息,但我想显示至少的onResume activty的新邮件。在按下发送按钮后,我可以显示发送的消息,但没有收到的消息在第一次活动创建时工作正常。

编辑:我做了更多的调试,事实证明问题不是在恢复活动,如果我不第一次使用接收()函数,并恢复后回去的活动,然后接收()将工作,这意味着,函数里收到():getListView().setSelection(messagex.size()-1);只能工作一次。 第一次接收消息或下一次当且仅当第一次在活动时不被调用。

回答

1

消息实例不会被破坏,当您恢复活动时,会产生问题。确保当调用unopop时,你的mhandler销毁所有对象的实例。

+0

但我确实试图停止looper在onDestroy方法中使用looper.quit,应用程序崩溃。我曾尝试mhandler.removeCallbackAndMessages(null);没有looper.quit这也失败了 – Harshit

+0

它确实帮了我一些其他的形式,我所做的只是使用静态来创建messagex的单个实例,它做了窍门,但有一个最后的手段,接收到的消息仅在我发送时才显示信息 – Harshit

1

在代码中没有地方可以保存您的messagex ArrayList。当你通过回击退出你的活动时,你的数组会被破坏(垃圾收集会照顾它)。

当您重新启动您的活动时,您的messagex ArrayList被重新创建,它是一个全新的变量。

事实上,你不是重新启动你的活动,你正在创建一个新的实例。

编辑:

我从来没有曾与XMPPConnection前对象,但别的东西值得尝试如下:
当绑定到该服务,你打电话connection2.getChatManager().addChatListenerarg0.addMessageListener但解除绑定你的时候'不会调用任何removeXXX方法。我可能是因为你没有删除你的监听器,整个XMPPConnection对象仍然引用了一个死活动的监听器,并且它们没有被垃圾收集。

+0

是的,我不想恢复以前的消息,但是一旦恢复活动,新消息不会显示在空白列表视图中。在活动的简历上按下发送按钮后,我可以看到发送的消息,但没有收到消息。我可以在调试器中看到接收函数被调用,并且Toast也完成了,但它不会更改适配器数据。感谢您的时间 – Harshit

+0

嗯,我看到的唯一可疑的事情是Runnable对象内的Toast消息。切勿从主线程以外的线程更新UI,包括Toast。 – Merlevede

+0

好的,将删除并查看它是否改变了其他任何东西,但不太可能,因为一旦第一次创建活动,显示和Toast都可以正常工作,并且一旦我再次返回并重新开始活动,只有Toast可以工作。有我缺少的适配器方面,因为我在android的noob我很笨,试图dubgging了解什么可能是错误的,但控制确实去接收()函数 – Harshit

0

在上面提到的代码中,在活动恢复或服务获取消息后,您从未更新过自定义适配器类中的ArrayList。

解决方案:

改变你定义适配器构造函数,public ChattingAdapter(Context context)否则创建一个方法如下

public void updateMessage(ArrayList<ChatMessage> messages) { 
    this.mMessages.clear(); 
    this.mMessages = messages; 
    notifyDataSetChanged(); 
} 

,并在自定义适配器类如提及的声明初始化mMessages作为new ArrayList<ChatMessage>();本身,你会得到空指针异常。

而在你hotListener Activty,addNewMessage(ChatMessage米)方法应该提及我认为当你尝试恢复活动,您还在运行以前mHandler运行,因此你的问题就出在下面更改

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); 
} 
+0

,按照指定创建更改之后,即使是如上所述的第一次,我也不再看到它工作,甚至不显示发送的消息。谢谢你的帮助 。 – Harshit

+0

我确实修改了你的代码,但是它也一样,如果你仔细看看我的代码,我甚至都没有在任何地方使用addNewMessage,谢谢你的时间,我期待将它存储在数据库中并以某种方式更新列表 – Harshit