【问题标题】:Android: Refresh ListView in first activity on return from second activityAndroid:从第二个活动返回时刷新第一个活动中的 ListView
【发布时间】:2013-01-09 21:10:10
【问题描述】:

当用户关闭一个活动并返回到上一个活动时,我遇到了列表刷新问题。我发现这个问题很常见,但我无法解决。

我重写了 onResume 方法:

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

populateList() 是我用字符串列表填充 listView 的方法:

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

问题是,当第二个活动关闭时,新项目会再次添加到 ListView 中,所以我将每个项目都翻了一番。就像它没有刷新一样。

如果我将 notifyDataSetChanged() 放在 onResume() 中,它会抛出 nullPointerException,因为第一次启动活动时,第一次启动活动时没有初始化适配器。

我不知道如何处理。

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

【问题讨论】:

  • 保留一个成员变量来控制ListView 是否已经包含字符串。如果是这样,请不要致电populateList()
  • 问题在于list,你是如何填充这个的?
  • @Shelly - 但即使 ListView 包含字符串,我也需要调用 populateList()。我正在尝试刷新它。我不确定我是否理解你。
  • @ZdravkoVajudin:啊,对不起,我误会了。我会清除适配器,然后再次添加字符串。
  • @Sam - 我从设备中捕获 list_of_files 并将其放入 populateList() 中的列表中。然后我应用适配器。返回时,设备上的列表已更改,因此它再次执行相同操作并将其放入列表中。问题是在 ListView 中仍然有旧项目,而新项目只是在最后添加。所以它是重复的。

标签: android android-listview refresh android-activity onresume


【解决方案1】:

马上,您可以通过一个简单的条件语句轻松解决这个问题,该语句仅在适配器不是null 时执行命令:

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

但这在我看来,在更深层次上,您的代码可以在一定程度上进行重构以提高效率,但不一定更具功能性。


这样做:

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

【讨论】:

  • 我是这样说的,现在它又可以工作了,但是重复项目仍然存在问题。例如,我有 5 个项目,在第二个活动中更改了一个,返回时列表中还有旧的五个,1 个新的(在第二个活动中更改了一个)和 4 个旧的再次重复。如果最后一个被编辑是这样的:a,b,c,d,e,a,b,c,d,z
  • 您没有为我们提供足够的代码来充分帮助您。但是您需要检查初始化 list 集合的任何代码块是否不会再次被调用,大概是 onResume 您甚至需要我建议的内容,这让我担心事情并非如此。
  • 有效!只是一次更正。在最后一个else 中,arrayAdapter.notifyDataSetChanged(); 下面还必须是:arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item, list); listView.setAdapter(arrayAdapter); 如果不是,ListView 只包含旧数据。
【解决方案2】:

我从设备中捕获 list_of_files 并将其放入 populateList() 中的列表中。然后我应用适配器。返回时,设备上的列表已更改,因此它再次执行相同操作并将其放入列表中。问题是在 ListView 中仍然有旧项目,而新项目只是在最后添加。所以它是重复的。

一种基本方法是在添加新数据之前调用list.clear()。这应该会删除旧数据并防止重复。 (但如果没有看到有问题的代码,很难提供准确的答案......)


加法
您应该将此代码添加到 GetAsyncTask 内的 onPostExecute() 方法中:

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

除非GetAsyncTask 嵌套在您的活动中,否则您需要将一些变量移动到GetAsyncTask 使用它。但这种方法更好,因为它不会强制 Activity 等待结果(这可能会导致“应用程序无响应”错误。)

【讨论】:

  • 感谢 AsyncTask 的建议!我给了你一个:)
【解决方案3】:

您只显示了应用程序代码的一部分,所以我可能在这里偏离了基础,但我猜您正在使用光标返回 list 变量并使用 list 创建一个 ArrayAdapter...

如果您希望数据“新鲜”,为什么不将 CursorLoader 与 LoaderManager 一起使用? LoaderManager 有几个好处(例如将查询从 UI 线程中移出),并且在监视数据库的更改时,LoaderManager 会为您完成一些繁重的工作。

有一篇博文对我很有帮助 - http://www.androiddesignpatterns.com/2012/07/understanding-loadermanager.html

这一切都假设您从数据库中提取数据...

【讨论】:

    【解决方案4】:

    问题是您在调用函数 populateList() 时没有先清除列表。这种方式填充列表只是简单地添加到以前的内容。

    这是正确的方法:

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

    我也不确定你为什么在函数populateList()中设置了适配器

    你应该试试这个。

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

    这样,通过取出适配器,您可以简单地在 onResume() 函数中使用它

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

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 2016-04-18
      • 2013-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多