简体   繁体   English

Android:从第二个活动返回时,在第一个活动中刷新ListView

[英]Android: Refresh ListView in first activity on return from second activity

I have a problem with list refresh when user closes one activity and returns to previous. 当用户关闭一个活动并返回到上一个活动时,我遇到列表刷新问题。 I see that problem is very common but I can't solve it. 我发现这个问题很常见,但我无法解决。

I overridden onResume method: 我重写了onResume方法:

@Override
public void onResume() {
    super.onResume();
    populateList();
}

populateList() is a method where I populate listView with list of Strings: populateList()是一个方法,我用字符串列表填充listView:

arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item,list);
listView.setAdapter(arrayAdapter);

The problem is that when second activity is closed, new items are just added again in the ListView so I have every item doubled. 问题是,当第二个活动关闭时,新项目将再次添加到ListView中,因此我将每个项目加倍。 Like it's not refreshed. 喜欢它没有刷新。

If I put notifyDataSetChanged() in onResume() it throws me nullPointerException because when activity is started first time there is no adapter initialized when activity is first time started. 如果我在onResume()中放置notifyDataSetChanged(),它会抛出nullPointerException,因为当第一次启动活动时,第一次启动活动时没有初始化适配器。

I'm not sure how to handle this. 我不知道如何处理这个问题。

public class testActivity extends Activity {


    private int id=1;
    private ListView listView;
    private CustomArrayAdapter arrayAdapter;
    private ArrayList<String> list = new ArrayList<String>();
    ArrayList<Item> objectList = new ArrayList<Item>();

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

    }

    @Override
    public void onResume() {
        super.onResume();
        populateList();
    }

    private void populateList() {
        try {
            objectList = new GetAsyncTask(id).execute();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TimeoutException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        int size = objectList.size();
        String name;

        for (int i = 0; i < size; i++) {
            name = objectList.get(i).getName();
            list.add(name);
        }

        arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item,
                list);
        listView.setAdapter(arrayAdapter);
    }
}

well right off the bat, you could easily knock this away with a simple conditional statement that performs the command only if the adapter isn't null : 好吧,你可以轻松地用一个简单的条件语句敲掉它,只有当适配器不为null时才执行命令:

    if (adapter != null) {
        adapter.notifyDataSetChanged();
    }

But this seems to me like, at a deeper level, your code could be re-factored somewhat to be more efficient, though not necessarily more functional. 但在我看来,在更深层次上,您的代码可能会在某种程度上重新考虑,以提高效率,但不一定更具功能性。


do it like this: 像这样做:

private int id = 1;
private ListView listView;
private CustomArrayAdapter arrayAdapter;
private ArrayList<String> list = new ArrayList<String>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
}

@Override
public void onResume() {
    super.onResume();
    populateList();
}

private void populateList() {

    ArrayList<Item> objectList;
    try {
        objectList = new GetAsyncTask(id).execute();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        e.printStackTrace();
    }

    list.clear();
    for (int i = 0; i <objectList.size(); i++) {
        String name = objectList.get(i).getName();
        list.add(name);
    }
    if (arrayAdapter == null) {
        arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item, list);
        listView.setAdapter(arrayAdapter);
    } else {
        arrayAdapter.notifyDataSetChanged();            
    }
}

I catch the list_of_files from device and put it in a list in populateList(). 我从设备中捕获list_of_files并将其放在populateList()中的列表中。 Then I apply adapter. 然后我申请适配器。 On return that list on device is changed so it again does the same and put it in a list. 返回时,设备上的列表已更改,因此它再次执行相同操作并将其放入列表中。 The problem is in ListView there are still old items and new items are just added at the end. 问题出在ListView中,仍有旧项目,最后只添加了新项目。 So it's duplicated. 所以这是重复的。

One basic approach is to call list.clear() before adding the new data. 一种基本方法是在添加新数据之前调用list.clear() This should erase the old data and prevent duplicates. 这应该删除旧数据并防止重复。 (But it's hard to provide an exact answer without seeing the code in question...) (但是如果没有看到有问题的代码,很难提供确切的答案......)


Addition 加成
You should add this code to your onPostExecute() method inside GetAsyncTask : 您应该将此代码添加到您的onPostExecute()内的方法GetAsyncTask

int size = objectList.size();
String name;

list.clear(); // or list = new ArrayList<String>();
for (int i = 0; i < size; i++) {
    name = objectList.get(i).getName();
    list.add(name);
}

arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item, list);
listView.setAdapter(arrayAdapter);

Unless GetAsyncTask is nested in your Activity, you will need to move a few variables to GetAsyncTask use this. 除非GetAsyncTask嵌套在您的Activity中,否则您需要将一些变量移动到GetAsyncTask使用它。 But this approach is better because it doesn't force the Activity to wait for results (which might cause an "Application Not Responding" error.) 但是这种方法更好,因为它不会强制Activity 等待结果(这可能会导致“Application Not Responding”错误。)

You are only showing part of the app code, so I may be offbase here, but I'm guessing you are using a Cursor to return the list variable and use list to create an ArrayAdapter... 你只是显示部分应用程序代码,所以我可能在这里偏离,但我猜你正在使用Cursor返回list变量并使用list来创建一个ArrayAdapter ...

If you want the data to be 'fresh', why not use a CursorLoader with the LoaderManager? 如果您希望数据为“新鲜”,为什么不将CursorLoader与LoaderManager一起使用? There are several benefits to the LoaderManager (like moving the query off of the UI thread), and the LoaderManager does a bit of the heavy lifting for you when it comes to monitoring the DB for changes. LoaderManager有几个好处(比如从UI线程中移出查询),并且在监视数据库的更改时,LoaderManager为您做了一些繁重的工作。

There is a blog post that I've found quite helpful - http://www.androiddesignpatterns.com/2012/07/understanding-loadermanager.html 我发现有一篇博文非常有用 - http://www.androiddesignpatterns.com/2012/07/understanding-loadermanager.html

This is all assuming you are pulling the data from a database... 这是假设您从数据库中提取数据...

The problem is that you are calling the function populateList() without clearing the list first. 问题是您正在调用函数populateList()而不先清除列表。 That way populate list simply just adds to the previous content. 这样填充列表只是添加到以前的内容。

This would be a right way : 这将是一种正确的方式:

public void onResume() {
super.onResume();
list = new ArrayList<String>();
populateList();  }

I am also not sure as to why you have set the adapter inside the function populateList() 我也不确定为什么你在函数populateList()设置了适配器

You should try this. 你应该试试这个。

    private ArrayList<String> list = new ArrayList<String>();

    private ArrayList<String> populateList() {
            try {
                objectList = new GetAsyncTask(id).execute();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (TimeoutException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            int size = objectList.size();
            String name;

            for (int i = 0; i < size; i++) {
                name = objectList.get(i).getName();
                list.add(name);
            }
 return list;
        }
     arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item,
                    populateList());
            listView.setAdapter(arrayAdapter);

That way by having the adapter out you can simply have this in the onResume() function 通过使用适配器,你可以在onResume()函数中使用它

public void onResume() {
    super.onResume();
    list = new ArrayList<String>();
    }

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

相关问题 从第二个活动返回后在第一个活动中更新 Listview - Update Listview in first activity after returning from second activity 如何将第一个Activity中的数据保存到第二个Activity中? - How to save the data in my ListView from the first Activity to the second Activity? Android:从第二个活动刷新cursorloader - Android: Refresh cursorloader from a second activity Android从另一个活动刷新ListView适配器 - Android refresh listview adapter from another activity 来自第二个活动的列表视图上的Android Next项目 - Android Next item on listview from second Activity 从第三个活动返回第一个活动并跳过第二个活动 - Return back to first activity from third and skipping the second activity 从Android中的第一个AsyncTask调用第二个活动 - Calling the second activity from AsyncTask of the first in Android 如何在android中从单击按钮的第一个活动和从第二个按钮单击的第三个活动中进行第二个活动 - How to go second activity from first activity on button click and Third activity from Second on button click in android 第二次活动使我回到了Android的第一个活动 - Second Activity returns me to first activity in Android Android关闭第二项活动,然后转到第一项活动 - Android Close Second activity and move to first activity
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM