【问题标题】:Notify RecyclerView adapter database changed通知 RecyclerView 适配器数据库已更改
【发布时间】:2015-01-28 01:23:55
【问题描述】:

我的MainActivity调用了一个片段,

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.container, PlaceholderFragment.newInstance(position + 1),
                    "placeHolderFragmentTag")
            .commit();
}

placeholderFragment 用适配器填充RecyclerView

    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

@Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            dbHelper = new DatabaseHelper(getActivity().getApplicationContext());
            dbHelper.getWritableDatabase();
            dbHelper.openDataBase();

            adapterUpcomingGames = new AdapterUpcomingGames(retrieveGames(dbHelper.getUpcomingGames()));
        }

adapterUpcomingGames。适配器从用户输入的数据库中获取数据,即即将到来的体育赛事列表。

@Override   // still placeholderFragment
        public void onActivityCreated(Bundle savedInstanceState)
        {
            super.onActivityCreated(savedInstanceState);

            mRecyclerView.setHasFixedSize(true);
            mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
            mRecyclerView.setItemAnimator(new DefaultItemAnimator());

            switch(getArguments().getInt(ARG_SECTION_NUMBER))
            {
                case 1:     // This will be upcoming games
                    mRecyclerView.setAdapter(adapterUpcomingGames);
                    break;
                case 2:     // This will be past games
                    AdapterPastGames adapterPastGames;
                    adapterPastGames = new AdapterPastGames(retrieveGames(dbHelper.getPastGames()));
                    mRecyclerView.setAdapter(adapterPastGames);
                    break;
                default:    // Default is, well, anything that will work.
                    adapterUpcomingGames1 = new AdapterUpcomingGames(retrieveGames(dbHelper.getGames()));
                    mRecyclerView.setAdapter(adapterUpcomingGames1);
            }

            newGame.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View arg0){

                    Intent createGame = new Intent(getActivity(),
                            ActivityCreateGame.class);
                    startActivity(createGame);
                    adapterUpcomingGames.notifyDataSetChanged();
                }
            });

            setRetainInstance(true);
        }

在此视图中,有一个添加游戏的按钮,即修改数据库。我通过调用一个承载片段的新活动activityCreateGame 来实现这一点,

@Override // activityCreateGame
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_create_game);

    fragmentCreateGame = new FragmentCreateGame();
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction()
            .attach(fragmentCreateGame)
            .replace(R.id.newGameContainer, fragmentCreateGame)
            .commit();

    restoreActionBar();
}

fragmentCreateGame,允许用户输入所需的信息,然后将其附加到数据库中。用户使用该活动中导航栏上的选项保存此信息。

@Override  // activityCreateGame
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
            case android.R.id.home:
                finish();
                break;
            case R.id.action_save:
                // check if an error has occured
                if (fragmentCreateGame.CreateNewGame())
                {
                    Toast toast = Toast.makeText(this, R.string.toast_success_game_create,
                            Toast.LENGTH_SHORT);
                    toast.show();

                    finish();
                }
                else{
                    Toast toast = Toast.makeText(this, R.string.toast_failed_game_create,
                            Toast.LENGTH_SHORT);
                    toast.show();
                }
                break;
        }
        return super.onOptionsItemSelected(item);
    }

该操作完成activityCreateGame。现在,我该如何通知适配器,回到placeholderFragment 数据库已更新,从而更新RecyclerView 以更新自身?

【问题讨论】:

  • 贴一些代码帮助理解
  • 从它的声音来看,考虑一个从接口定制的监听器,或者Activity for Reuslt
  • 我想知道是否有类似的东西。我已经添加了一些代码,但我也会看看。

标签: android database android-fragments android-adapter android-recyclerview


【解决方案1】:

通过查看您的代码,我可以为您想到三个解决方案。按照(我认为)解决方案的质量从最低到最好的顺序。

  1. 将您的片段fragmentCreateGame 移至您的第一个活动托管
  2. Start Activity For Result
  3. 使用Otto Event Bus。我会推荐奥托。特别是如果您可能有多个对象在监听一个事件。

首先将 Otto 添加到您的项目中。在您的 build.gradle 中,将此添加到您的依赖项中。

dependencies {
   ....
   compile 'com.squareup:otto:1.3.6'
   ....
} 

在需要通知的活动中,在 onCreate 开头添加:

 Bus bus = new Bus();
 bus.register(this);

然后,创建一个“事件”类。它只是您传递给订阅者的一个对象。您也可以向这些添加信息,以传递更多信息。

public class SomeCoolEvent{
      private String yourWisdom;
      public SomeCoolEvent(String yourWisdom){
           this.yourWisdom = yourWisdom;
      }

      public String getWisdom(){
          return yourWisdom;
      }
 }

然后,在你的班级正在做一些事情来通知其他班级,这样做:

Bus bus = new Bus();
bus.post(new SomeCoolEvent(yourWisdomStringFromThisClass));

现在,返回到您的第一个活动,添加一个带有 @Subscribe 注释的方法

 @Subscribe
 public void onAnyMethodNameYouWantCauseItDoesntMatter(SomeCoolEvent event){
       //this will be called when ANY class calls bus.post(SomeCoolEvent)
       String boomYouAreNotified = event.getWisdom();
  }

在您的 @Subscribe 方法中,有几件事需要注意。 * 方法名无关紧要,所以给它一些对你有意义的东西。我喜欢在它前面加上“on”,因为它就像一个回调。 * 方法必须是public,返回void。 * 您没有显式调用此方法,因此某些 IDE 可能会显示为未使用。 Android Studio 将允许您使用“ALT + ENTER”修复该问题,然后选择“_ignore warnings for methods annotated with Subscribe”。 *您应该在销毁时致电bus.unregister(this)。 *您可以让多个班级听一个帖子。

现在,如果您开始在不同的线程上运行,事情会变得更加复杂。如果你这样做了,我提供的 Otto 页面底部有解决方案。

【讨论】:

  • Otto 现在可能有点过分了。但我会看看它。做了一些修改,我的 ActivityForResult 工作得很好,但是 RecyclerView 没有更新。适配器似乎正在获取 notifyDataSetChanged,但视图没有发生更新。
  • @JoshuaSutherland 因为您没有向适配器添加任何项目。创建适配器时,您正在查询数据库。这适用于第一个。但是当您调用notifyDataSetChanged 时,它不会再次调用它。您需要创建数据的 ArrayList,然后创建适配器,并将此列表传入。然后将新数据添加到此列表中,然后调用 notifyDataSetChanged。
  • 好的。这就说得通了。那么在这种情况下什么是最好的呢?我应该在 RESULT_OK 上重新查询数据库吗?
  • 是的。请注意适配器、listView 和列表的实例。如果您重新查询列表,并将列表设置为您的结果,您的适配器可能会遇到“看到”此更改的问题。如果是这样,只需重新创建适配器并将其设置为您的列表视图。
  • 因此,如果您可以管理所有实例,只需将您的项目添加到列表中。不要将它们设置到列表中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-15
  • 1970-01-01
  • 2013-12-13
  • 1970-01-01
相关资源
最近更新 更多