简体   繁体   English

从其他片段更新Listview

[英]Update Listview in from other fragment

I am using the tutorial on Manishkpr to create a app where you swipe between 1) layoutOne: here you create a file and 2) layoutTwo: shows a listview of all created files in a certain folder. 我正在使用Manishkpr上的教程来创建一个应用程序,你可以在其中滑动1)layoutOne:在这里你创建一个文件和2)layoutTwo:显示某个文件夹中所有创建文件的列表视图。

Problem: if you create a file, it is not immediately shown in the listview. 问题:如果您创建了一个文件,它不会立即显示在列表视图中。 I found that I should use this code in my LayoutOne.java: 我发现我应该在LayoutOne.java中使用此代码:

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

In LayoutTwo.java I added: 在LayoutTwo.java中,我添加了:

private static final String TAG = "TESTTWO";

//and the function getAdapter:

public CustomArrayAdapter getAdapter() {

        return adapter;
    }

However, I am getting a nullpointer exception on fragment.getAdapter().notifyDataSetChanged(); 但是,我在fragment.getAdapter().notifyDataSetChanged();上获得了一个nullpointer异常fragment.getAdapter().notifyDataSetChanged(); . How can I solve this, and is this the best way actually? 我怎么能解决这个问题,这实际上是最好的方法吗?

EDIT 编辑

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

I am using the tutorial on Manishkpr to create a app where you swipe between 1) layoutOne: here you create a file and 2) layoutTwo: shows a listview of all created files in a certain folder. 我正在使用Manishkpr上的教程来创建一个应用程序,你可以在其中滑动1)layoutOne:在这里你创建一个文件和2)layoutTwo:显示某个文件夹中所有创建文件的列表视图。

Problem: if you create a file, it is not immediately shown in the listview. 问题:如果您创建了一个文件,它不会立即显示在列表视图中。

If you just have two layouts to swipe that means both will have their views in memory and available to access. 如果您只有两个布局可以滑动,这意味着它们将在内存中拥有视图并可供访问。 You could then assign an id to the ListView and when it's time to refresh the data simply look for that ListView in the Activity , get its adapter and update it, something like this: 然后,您可以为ListView分配一个id,当需要刷新数据时,只需在Activity查找ListView ,获取其适配器并更新它,如下所示:

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

No matter if you call notifyDataSetChanged() on the adapter the ListView will not update because it doesn't see the new file, from its point of view the data set is intact. 无论你是否在适配器上调用notifyDataSetChanged() ,ListView都不会更新,因为它没有看到新文件,从它的角度来看数据集是完整的。 Depending on how your adapter looks like you have two options: 根据适配器的外观,您有两种选择:

Rebuild the data of the ListView , basically redo what you did when the ListView is first constructed: check that directory and re-list all files. 重建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);
     }
}

Or you could manually create a RecordFile object for the newly created file and add that to the existing adapter: 或者,您可以为新创建的文件手动创建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();

I don't know how your adapter looks like so try what I said and if it doesn't work please post the code for the adapter. 我不知道你的适配器是怎么样的,所以试试我说的,如果它不起作用,请发布适配器的代码。

I think this is because the viewpager loads the layoutTwo, BUT you do not refresh it with the notifyDataSetChanged. 我认为这是因为viewpager加载了layoutTwo,但你没有使用notifyDataSetChanged刷新它。 You only refresh the data of the LayoutTwo, but it does not get refreshed, since the viewpager has a method: pager.setOffscreenPageLimit(1); 您只刷新LayoutTwo的数据,但它不会刷新,因为viewpager有一个方法: pager.setOffscreenPageLimit(1); AFAIK this is the default, so the next thing will happen in row: load LayoutOne, load LayoutTwo, do things in layoutOne, do things in layoutTwo. AFAIK这是默认的,所以接下来会发生在行中:加载LayoutOne,加载LayoutTwo,在layoutOne中做事,在layoutTwo中做事。 But as you see there will be no load layoutTwo afterwards. 但正如你所看到的,之后将没有负载布局。

I had a very similar problem and it is a kind of a workaround, but restarted the actvity (and pager.removeAllViews(); ) and it worked well without disturbing the user. 我有一个非常类似的问题,它是一种解决方法,但重新启动了pager.removeAllViews();pager.removeAllViews(); )并且它运行良好而不会打扰用户。

But to be certain that this causes the problem, put this in your code for a button clicklistener: 但要确定这会导致问题,请将其放入代码中以获取按钮clicklistener:

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

This will not solve your problem exactly, but you will able to see if the layoutTwo chaged or not, getting the cause of the problem. 这不能完全解决您的问题,但您将能够看到layoutTwo是否变形,从而解决问题的原因。

Had almost the same problem in a project a while ago. 不久前在一个项目中遇到了几乎相同的问题。

The solution was to add the Observer pattern to the application. 解决方案是将Observer模式添加到应用程序中。

Have a look at the official documentation about the problem: 查看有关该问题的官方文档:

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

What happens is that you register the different Fragments with the Activity that holds the Fragments . 会发生什么事是你注册不同的FragmentsActivity持有的Fragments Whenever one Fragment is changing, you make a callback to your Activity who in turn will act and deliver some message to one of the other Fragments . 每当一个Fragment是变化的,你做一个callback到您的Activity谁又将采取行动,并提供一些message给其他的一个Fragments

Then you can get for instance the ListView of the specific Fragment and update it or whatever you want to do. 然后,您可以获取特定FragmentListView并更新它或您想要做的任何事情。

It's really simple and powerful ;-) 它非常简单而且功能强大;-)

Hi maybe its a little late but I was struggling to do this and this is the way I managed to do it. 嗨,也许它有点晚了,但我正在努力做到这一点,这是我设法做到这一点的方式。

It definitely isn't the best way to do it but it's working. 它绝对不是最好的方法,但它正在发挥作用。

Initialize your fragments at the start so we can hold each instance of them and then select if we want to instantiate them. 在开始时初始化片段,这样我们就可以保存它们的每个实例,然后选择是否要实例化它们。

ExampleFragment searchFragment = null;
ExampleFragment fileListFragment = null;

Now change the FragmentStatePagerAdapter to the following so we use our previously initialiazed Fragments 现在将FragmentStatePagerAdapter更改为以下内容,以便我们使用以前初始化的Fragments

ExampleFragment searchFragment = null;
ExampleFragment fileListFragment = null;

Now on the PagerAdapter class: 现在在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;
    }

}

In this way we can call the methods inside of every fragment and communicate with them from the Main Activity without any view or context issue. 通过这种方式,我们可以调用每个片段中的方法,并从Main Activity与它们进行通信,而不会出现任何视图或上下文问题。

Then on the onTabSelected method of the action bar or any other "onChangeTab" like method you just reset call the method you want from your fragment. 然后在操作栏的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());
}

It's not elegant but it is working like a charm. 它不优雅,但它的工作就像一个魅力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM