我无法弄清楚如何在我的应用程序中正确使用notifyDataSetChanged [英] I cannot figure out how to correctly use notifyDataSetChanged within my app

查看:80
本文介绍了我无法弄清楚如何在我的应用程序中正确使用notifyDataSetChanged的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用ViewPager和Fragments创建标签的应用程序.

I have an app that uses a ViewPager and Fragments to create tabs.

在我的应用程序中,我具有聊天功能.每当接收或发送聊天时,它都会存储在数据库表中.接收到的聊天将进入不同的线程,并且用户的聊天将被输入到Chat fragmenet的EditText窗口中.

Within my app, I have a chat function. Whenever a chat is received or sent, it is stored in a table of the database. The received chats are coming in on a different thread, and the user's chats are being entered into an EditText window in the Chat fragmenet.

我有一个名为"LogChat.java"的类,可将聊天记录保存到数据库中.

I have a class called "LogChat.java" that saves the chats to the database.

我有一个显示聊天的SimpleCursorAdapter支持的ListView.此ListView在我的应用程序的聊天"片段中.

I have a ListView backed by a SimpleCursorAdapter that is displaying the chats. This ListView is in the Chat Fragment of my application.

一切正常,但ListView不会自动刷新以显示最新的聊天记录.在聊天"片段中,我有这种显示聊天的方法:

Everything is working perfectly, except the ListView is not automatically refreshing to show the latest chats. In the Chat fragment, I have this method to display the chats:

displayChats()

public void displayChats(){
    DatabaseHelper databaseHelper = new DatabaseHelper(getActivity());
    Cursor chatsCursor = databaseHelper.getChatsCursor();
    String[] fromColumns = {chatInfo, chatContent};
    int[] toViews = {R.id.chat_info, R.id.chat_content};
    SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(getContext(), R.layout.line_of_chat, chatsCursor, fromColumns, toViews, 0);
    ListView listView = (ListView) rootView.findViewById(R.id.chat_text_display);

    listView.setAdapter(simpleCursorAdapter);
    databaseHelper.close();
}

我要从输入中读取聊天记录,并将其保存到数据库中:

And I have this to read the chat from the input, and save it to the database:

getView()

@Override
public View getView(){
    Button sendChatButton = (Button) rootView.findViewById(R.id.send_chat_button);
    EditText chatEntryWindow = (EditText) rootView.findViewById(R.id.chat_entry_window);

    sendChatButton.setOnClickListener(new View.OnClickListener(){
        String message = chatEntryWindow.getText().toString();

        LogChat logChat = new LogChat();
        logChat.addMessage(message);

        displayChats();
    });
}

在侦听器线程中,我传递了对Main Activity的引用,并使用该引用将聊天发送到LogChat.java以便存储在数据库中:

In the listener thread, I pass in a reference to the Main Activity, and use that to send the chat to LogChat.java for storage within the database:

Listener.java

public class Listener implements Runnable(){
    private MainActivity mainActivity;

    public Listener(MainActivity mainActivity){
        this.mainActivity = mainActivity;
    }

    @Override
    public void run(){
        LogChat logChat = new LogChat();
        logChat.addMessage(message);
    }
}

就像我说的那样,除了刷新ListView以显示新接收到的聊天记录外,所有其他方法都有效.我已经成功存储了所有聊天记录(用户和所有收到的聊天记录),并且如果我对自己的操作方式(即输入本地聊天记录)感到困惑,它们将正确显示在我的ListView中.

Like I said, this all works, except for refreshing the ListView to show the new received chats. I am successfully storing all chats (the user's and all received chats), and they will correctly display in my ListView if I am tricky with the way I do it (i.e., enter a local chat).

现在,为了查看收到的聊天,我必须在本地输入一个聊天,调用displayChats()方法,该方法将更新ListView,该ListView显示我输入的聊天以及ListView中最近收到的所有其他聊天.

Right now, in order to see the received chats, I have to enter a chat locally, which calls the displayChats() method, which updates the ListView, which shows my entered chat and all other recently received chats in the ListView.

我知道我应该使用notifyDataSetChanged(),但是我一生无法弄清楚如何使用它.我已经尝试将头部缠绕一会儿了,但是我只是无法得到它".

I know that I am supposed to use notifyDataSetChanged(), but I cannot, for the life of me, figure out how to use it. I have been trying to wrap my head around it for a while now, but I just cannot "get it".

我知道我应该像这样在simpleCursorAdapter变量上调用notifyDataSetChanged():

I know I am supposed to call notifyDataSetChanged() on the simpleCursorAdapter variable like this:

simpleCursorAdapter.notifyDataSetChanged();

但是我不确定如何从我的LogChats类或侦听器线程访问它.或者,就此而言,使用与SimpleCursorAdapter相同的类的getView()方法.我认为最好从LogChats类中进行操作,因此有一个中心点可以在数据库并将视图全部刷新到一个地方.

But I am not sure how to access that from my LogChats class or my listener thread. Or, for that matter, from the getView() method of the same class the SimpleCursorAdapter is being used in. I thought it would be a good idea to do it from the LogChats class so there is a central point for logging the chats in the database and refreshing the view all in one place.

我知道notifyDataSetChanged()一直被使用,所以我认为我只是想知道如何正确使用它,但是仍然被我阻止了.

I know that notifyDataSetChanged() is used all the time, so I figure I am just blocked on being able to figure out how to properly use it, but I am blocked nonetheless.

推荐答案

看来,这里的主要问题是将添加数据的事件放到适配器所在的Fragment中.

It looks like the main issue here is getting the data added event down to the Fragment where the adapter lives.

您可以只从侦听器在MainActivity中调用一个公共方法,该方法使用对Fragment的引用来调用将在适配器上调用notifyDataSetChanged()的公共方法.

You can just call a public method in MainActivity from your listener, that uses a reference to the Fragment to call a public method that will call notifyDataSetChanged() on the adapter.

首先,在FragmentPagerAdapter中使用instantiateItem()覆盖获取对您的ChatFragment的有效引用:

First, use an instantiateItem() override in your FragmentPagerAdapter to get a valid reference to your ChatFragment:

public class ViewPagerAdapter extends FragmentPagerAdapter {
    public ChatFragment chatFragment;

    //...

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return new ChatFragment();
            case 1:
                ...
            default:
                return null;
        }
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
      Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
      if (position == 0) {
        chatFragment = (ChatFragment) createdFragment;
      }
      return createdFragment;
    }
}

然后,在MainActivity中定义将中继数据更改事件的方法:

Then, define the method in MainActivity that will relay the data changed event:

public void dataChanged() {
    //only update if the user is currently on the ChatFragment
    if (mViewPager.getCurrentItem() == 0 && mPagerAdapter.chatFragment != null) {
        mPagerAdapter.chatFragment.listViewDataChanged();
    }
}

然后在您的ChatFragment中定义listViewDataChanged()方法,并确保适配器是Fragment类的成员变量:

Then define the listViewDataChanged() method in your ChatFragment, and make sure that the adapter is a member variable of the Fragment class:

public void listViewDataChanged() {
    simpleCursorAdapter.notifyDataSetChanged();
}

//Class member variable:    
SimpleCursorAdapter simpleCursorAdapter;

public void displayChats(){
    DatabaseHelper databaseHelper = new DatabaseHelper(getActivity());
    Cursor chatsCursor = databaseHelper.getChatsCursor();
    String[] fromColumns = {chatInfo, chatContent};
    int[] toViews = {R.id.chat_info, R.id.chat_content};
    //modified:
    simpleCursorAdapter = new SimpleCursorAdapter(getContext(), R.layout.line_of_chat, chatsCursor, fromColumns, toViews, 0);
    ListView listView = (ListView) rootView.findViewById(R.id.chat_text_display);

    listView.setAdapter(simpleCursorAdapter);
    databaseHelper.close();
}

并将其链接在一起,当数据更改时,从侦听器调用dataChanged().请注意,如果此Runnable在其自己的线程上运行,则需要使用runOnUiThread():

And to link it all together, call dataChanged() from the Listener when the data changes. Note that if this Runnable is running on it's own Thread, you will need to use runOnUiThread():

public class Listener implements Runnable(){
    private MainActivity mainActivity;

    public Listener(MainActivity mainActivity){
        this.mainActivity = mainActivity;
    }

    @Override
    public void run(){
        LogChat logChat = new LogChat();
        logChat.addMessage(message);
        //added:
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                 mainActivity.dataChanged();
            }
        });

    }
}

这篇关于我无法弄清楚如何在我的应用程序中正确使用notifyDataSetChanged的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆