从其他片段更新Listview

时间:2013-04-10 11:07:31

标签: android listview fragment

我正在使用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();上获得了一个nullpointer异常。我怎么能解决这个问题,这实际上是最好的方法吗?

修改

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

4 个答案:

答案 0 :(得分:8)

  

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

     

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

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

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

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

答案 1 :(得分:1)

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

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

但是要确定这会导致问题,请将其放在代码中以获取按钮clicklistener:

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

这不能完全解决你的问题,但是你可以看到layoutTwo是否变形,找出问题的原因。

答案 2 :(得分:1)

不久前项目中的问题几乎相同。

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

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

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

您所注册的是Fragments注册ActivityFragments的{​​{1}}。每当Fragment一个callback发生变化时,您就Activitymessage提出FragmentsListView将会采取行动并将Fragment传递给另一个{{1}}。< / p>

然后,您可以获取特定{{1}}的{​​{1}}并更新它或您想要做的任何事情。

它非常简单和强大; - )

答案 3 :(得分:0)

嗨,也许它有点晚了,但我很难做到这一点,这就是我设法做到的方式。

这绝对不是最好的方法,但它正在发挥作用。

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

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

它并不优雅,但却像魅力一样。