2

我正在使用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);
4

4 回答 4

8

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

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

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

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

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

于 2013-04-12T17:44:07.457 回答
1

我认为这是因为 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 是否发生变化,从而找到问题的原因。

于 2013-04-12T16:32:35.210 回答
1

前段时间在一个项目中遇到了几乎相同的问题。

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

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

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

发生的情况是您将不同Fragments的内容注册Activity到拥有Fragments. 每当一个人Fragment发生变化时,你就会callback对你的Activity人做一个,然后你会采取行动并将一些东西传递message给另一个人Fragments

然后,您可以获得例如ListView特定的Fragment并更新它或您想做的任何事情。

它非常简单而强大;-)

于 2013-04-12T23:16:45.773 回答
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());
}

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

于 2015-01-27T03:05:44.137 回答