【问题标题】:Update Listview in from other fragment从其他片段更新 Listview
【发布时间】:2013-04-10 11:07:30
【问题描述】:

我正在使用Manishkpr 上的教程创建一个应用程序,您可以在其中滑动 1)layoutOne:在这里创建一个文件和 2)layoutTwo:显示某个文件夹中所有创建文件的列表视图。

问题:如果您创建一个文件,它不会立即显示在列表视图中。我发现我应该在我的 LayoutOne.java 中使用这段代码:

   LayoutTwo fragment = (LayoutTwo) getFragmentManager().findFragmentByTag("TESTTWO");
            fragment.getAdapter().notifyDataSetChanged();

在 LayoutTwo.java 我添加了:

private static final String TAG = "TESTTWO";

//and the function getAdapter:

public CustomArrayAdapter getAdapter() {

        return adapter;
    }

但是,我在fragment.getAdapter().notifyDataSetChanged(); 上遇到了一个空指针异常。我该如何解决这个问题,这实际上是最好的方法吗?

编辑

myList = new ArrayList<RecordedFile>();

        File directory = Environment.getExternalStorageDirectory();
        file = new File(directory + "/test/");

        File list[] = file.listFiles();

        for (int i = 0; i < list.length; i++) {
            if (checkExtension(list[i].getName()) == true) {

                RecordedFile q = new RecordedFile();
                q.setTitle(list[i].getName());
                q.setFileSize(readableFileSize(list[i].length()));


                myList.add(q);
            }
        }

        adapter = new CustomArrayAdapter(myContext,
                R.layout.listview_item_row, myList);
        listView.setAdapter(adapter);

【问题讨论】:

  • 谁能帮帮我?现在搜索了几天并感到头疼.. :)

标签: android listview fragment


【解决方案1】:

我正在使用 Manishkpr 上的教程来创建一个应用程序,您可以在其中滑动 在 1) layoutOne: 在这里你创建一个文件和 2) layoutTwo: 显示一个 某个文件夹中所有创建文件的列表视图。

问题:如果您创建一个文件,它不会立即显示在 列表视图。

如果您只有两个布局可以滑动,这意味着两个布局都将在内存中拥有它们的视图并且可以访问。然后,您可以为ListView 分配一个ID,当需要刷新数据时,只需在Activity 中查找ListView,获取其适配器并对其进行更新,如下所示:

ListView list = (ListView) getActivity().findViewById(R.id.theIdOfTheList);
((BaseAdapter)list.getAdapter()).notifyDataSetChanged();

无论您是否在适配器上调用notifyDataSetChanged(),ListView 都不会更新,因为它看不到新文件,从它的角度来看,数据集是完整的。根据您的适配器的外观,您有两种选择:

重建ListView的数据,基本上重做ListView第一次构建时所做的:检查该目录并重新列出所有文件。

// create the new file
File directory = Environment.getExternalStorageDirectory();
file = new File(directory + "/test/");
File list[] = file.listFiles();
ListView list = (ListView) getActivity().findViewById(R.id.theIdOfTheList);
// I'm assuming your adapter extends ArrayAdapter(?!?)
CustomArrayAdapter caa = (CustomArrayAdapter) list.getAdapter();
caa.clear();
for (int i = 0; i < list.length; i++) {
     if (checkExtension(list[i].getName())) {
         RecordedFile q = new RecordedFile();
         q.setTitle(list[i].getName());
         q.setFileSize(readableFileSize(list[i].length()));
         caa.add(q);
     }
}

或者您可以为新创建的文件手动创建 RecordFile 对象并将其添加到现有适配器:

ListView list = (ListView) getActivity().findViewById(R.id.theIdOfTheList);
(CustomArrayAdapter) caa = (CustomArrayAdapter) list.getAdapter();
File newFile = new File("directory" + "/test/theNewFileName.extension");
RecordFile rf = new RecordFile();
rf.setTitle(newFile.getName());
rf.setFileSize(readableFileSize(newFile.length()));
// have a method to return a reference of the data list(or a method
// to add the data directly in the adapter)
List<RecordFile> data = caa.getListData();
data.add(rf);
caa.notifyDataSetChanged();

我不知道你的适配器是什么样子,所以试试我说的,如果它不起作用,请发布适配器的代码。

【讨论】:

  • 我的代码没有出现任何错误,这很好!但它不会更新 ListView...:s 有什么想法吗?
  • @MatthiasVanb 你能解释一下ListView 显示的内容吗?它如何“查看”特定目录中的文件(例如在应用程序启动时它如何查看当前文件)?
  • 它基本上是我通过 listFiles() 函数获得的文件夹中文件的列表视图。然后,我将信息放在我在 CustomAdapter 中使用的 RecordFile 类的实例中,并在正确的位置显示它们。我用代码@Luksprog 编辑了我的问题
  • 我今天会试试这个@Luksprog,这里有一些延迟:) Ps,知道什么是最有效的选择吗?
  • 我用第一种方式处理!我现在在文件夹中有 600 个项目,而且速度仍然很快!谢谢你的协助!呜呼!你得到了我的50分! :p @Luksprog
【解决方案2】:

我认为这是因为 viewpager 加载了 layoutTwo,但是您没有使用 notifyDataSetChanged 刷新它。你只刷新了 LayoutTwo 的数据,但它并没有被刷新,因为 viewpager 有一个方法:pager.setOffscreenPageLimit(1);AFAIK 这是默认的,所以接下来的事情会在行中发生:加载 LayoutOne,加载 LayoutTwo,做事情layoutOne,在 layoutTwo 中做事。但正如你所见,之后将不会加载 layoutTwo。

我遇到了一个非常相似的问题,这是一种解决方法,但是重新启动了活动(和 pager.removeAllViews(); )并且它运行良好而不会打扰用户。

但要确定这会导致问题,请将其放入按钮点击侦听器的代码中:

viewPager.removeAllViews();
finish();
startActivity(new Intent(MyActivity.this, MyActivity.class));

这并不能完全解决您的问题,但您可以查看 layoutTwo 是否发生变化,从而找出问题的原因。

【讨论】:

    【解决方案3】:

    不久前在一个项目中遇到了几乎相同的问题。

    解决方案是将观察者模式添加到应用程序中。

    查看有关问题的官方文档:

    http://developer.android.com/training/basics/fragments/communicating.html

    发生的情况是您将不同的Fragments 注册到拥有FragmentsActivity。每当一个Fragment 发生变化时,您就为您的Activity 创建一个callback,后者将采取行动并将一些message 传递给另一个Fragments

    然后您可以获取特定FragmentListView 并对其进行更新或任何您想做的事情。

    它真的很简单而且功能强大;-)

    【讨论】:

      【解决方案4】:

      嗨,也许有点晚了,但我一直在努力做到这一点,这就是我设法做到的方式。

      这绝对不是最好的方法,但它确实有效。

      在开始时初始化您的片段,以便我们可以保存它们的每个实例,然后选择是否要实例化它们。

      ExampleFragment searchFragment = null;
      ExampleFragment fileListFragment = null;
      

      现在将FragmentStatePagerAdapter 更改为以下内容,以便我们使用之前初始化的片段

      ExampleFragment searchFragment = null;
      ExampleFragment fileListFragment = null;
      

      现在在 PagerAdapter 类:

      class pagerAdapter extends FragmentStatePagerAdapter
      {
      
          public pagerAdapter(FragmentManager fm) {
              super(fm);
          }
      
          @Override
          public Fragment getItem(int position) {
              // getItem is called to instantiate the fragment for the given page.
              // Return a PlaceholderFragment (defined as a static inner class
              // below).
              switch (position) {
              case 0:
                  if (searchFragment != null) {
                      return searchFragment;
                  }
                  return searchFragment = new ExampleFragment();
              case 1:
                  if (downFragment != null) {
                      return downFragment;
                  }
                  return downFragment = new ExampleFragment();
              }
              return null;
          }
      
          @Override
          public int getCount() {
              return 2;
          }
      
          @Override
          public CharSequence getPageTitle(int position) {
              Locale l = Locale.getDefault();
              switch (position) {
              case 0:
                  return getString(R.string.title_section1).toUpperCase(l);
              case 1:
                  return getString(R.string.title_section2).toUpperCase(l);
              }
              return null;
          }
      
      }
      

      通过这种方式,我们可以调用每个片段内部的方法并从Main Activity 与它们进行通信,而不会出现任何视图或上下文问题。

      然后在操作栏的onTabSelected 方法或任何其他"onChangeTab" 类似的方法上,您只需从片段中调用您想要的方法。

      @Override
      public void onTabSelected(ActionBar.Tab tab,
              FragmentTransaction fragmentTransaction) {
          // When the given tab is selected, switch to the corresponding page in
          // the ViewPager.
          if ((tab.getPosition()) == 1) {
              downFragment.yourMethod();
          }
          mViewPager.setCurrentItem(tab.getPosition());
      }
      

      它并不优雅,但它就像一个魅力。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多