android -BaseAdapter 不会向 listView 添加新项目

Posted

技术标签:

【中文标题】android -BaseAdapter 不会向 listView 添加新项目【英文标题】:android -BaseAdapter doesn't add new items to listView 【发布时间】:2014-12-23 11:39:57 【问题描述】:

我不知道为什么我的 listView 没有添加新项目。

这是代码:

   ListAdapter ladap;

    private class GetContacts AsyncTask<Void, Void,ArrayList<HashMap<String, String>>>     
    @Override
    protected Void doInBackground(Void... arg0) 
        Spots_tab1_json sh = new Spots_tab1_json();
        String jsonStr = sh.makeServiceCall(url + page, Spots_tab1_json.GET);

        ArrayList<HashMap<String, String>> dataC = new ArrayList<HashMap<String, String>>();

        if (jsonStr != null) 
            try 
                JSONObject jsonObj = new JSONObject(jsonStr);
                contacts = jsonObj.getJSONArray(TAG_CONTACTS);

                    for (int i = 0; i < contacts.length(); i++) 
                    JSONObject c = contacts.getJSONObject(i);
                    String id = new String(c.getString("id").getBytes("ISO-8859-1"), "UTF-8");
                    String dates = new String(c.getString("dates").getBytes("ISO-8859-1"), "UTF-8");
                    String price = new String(c.getString("gheymat").getBytes("ISO-8859-1"), "UTF-8");
                    HashMap<String, String> contact = new HashMap<String, String>();
                    contact.put("id", id);
                    contact.put("dates", dates);
                    contact.put("price", price);
                    dataC.add(contact);
                
                
             catch (JSONException e) 
                goterr = true;
             catch (UnsupportedEncodingException e) 
                goterr = true;
            
         else 
            goterr = true;
        
        return dataC;
    

    @Override
    protected void onPostExecute(ArrayList<HashMap<String, String>> result) 
        super.onPostExecute(result);
        if (!isCancelled() && goterr == false) 
            if(ladap==null)
                ladap=new ListAdapter(MainActivity.this,result);
                lv.setAdapter(ladap);
            else
                ladap.addAll(result);
                ladap.notifyDataSetChanged();
            

    



    public class ListAdapter extends BaseAdapter 
    Activity activity;
    public ArrayList<HashMap<String, String>> list;

    public ListAdapter(Activity activity,ArrayList<HashMap<String, String>> list) 
        super();
        this.activity = (Activity) activity;
        this.list = list;
    

    public void addAll(ArrayList<HashMap<String, String>> result) 
        Log.v("this",result.size()+" resultsize");
        this.list = result;
        notifyDataSetChanged();
    

    public int getCount() 
        return contactList.size();
    

    public Object getItem(int position) 
        return contactList.get(position);
    

    public long getItemId(int arg0) 
        return 0;
    

    private class ViewHolder 
        TextView title,price;
        ImageView img ; 
        //RelativeLayout rl; 
    

    public View getView(int position, View convertView, ViewGroup parent) 
        ViewHolder holder;
        LayoutInflater inflater = activity.getLayoutInflater();
        if (convertView == null) 
            convertView = inflater.inflate(R.layout.item, null);
            holder = new ViewHolder();
            holder.title = (TextView) convertView.findViewById(R.id.title);
            holder.price = (TextView) convertView.findViewById(R.id.price);
            convertView.setTag(holder);
         else 
            holder = (ViewHolder) convertView.getTag();
        

            item = contactList.get(position);
            holder.price.setText(item.get("price"));
        return convertView;
    
    

在朋友的帮助下,我解决了我的上一个问题,新问题是这样的,适配器没有更新,所以它不会向 ListView 添加新行。我登录了,这里的 baseAdapter 中有 30 个新项目:

public void addAll(ArrayList<HashMap<String, String>> result) 
            Log.v("this",result.size()+" resultsize");
            this.list = result;
            notifyDataSetChanged();
        

但它没有添加到 listView。

你能帮我解决这个问题吗?

谢谢

【问题讨论】:

异常中的第一行告诉你究竟出了什么问题。您正在修改列表的数据集。在我看来,您正在动态创建全新的适配器,而不是使用您之前创建的适配器。 我认为您已经在外部声明适配器对象并检查 onPostExecute 是否为空,然后创建新实例,否则只需在适配器 updateList 方法中传递您的新数据,但您在 updateList 方法中也有更改代码,您无法设置this.list == list 而不是这个检查列表是否为空,然后创建列表的新实例并将所有数据添加到列表中,例如:list.addAll()。 你能发布你的整个活动吗?有些事情没有意义 @LokiSinclair 感谢您的回复,我更新了我的代码,但仍然收到此错误。你能帮我一个忙,看看我的新代码。也许你能帮我解决这个烦人的问题。谢谢 @HareshChhelana 感谢您的回复,我更新了我的代码,但仍然收到此错误。你能帮我一个忙,看看我的新代码。也许你能帮我解决这个烦人的问题。谢谢 【参考方案1】:

您已使用contactList ArrayList 来显示ListView 项目,并且您将在doinBackground() 中将数据更新到contactList,它运行不在ui 线程中的另一个线程,因此您无法从ui therad 更新ui 数据,因此您必须将本地ArrayList 用于doInBackground() 并将新的或更新的数据传递给 onPostExecute() ,后者将这些数据更新到 ui 线程。

private class GetContacts extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>> 
    @Override
    protected ArrayList<HashMap<String, String>> doInBackground(Void... arg0) 
        Spots_tab1_json sh = new Spots_tab1_json();
        String jsonStr = sh.makeServiceCall(url + page, Spots_tab1_json.GET);

        ArrayList<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
        if (jsonStr != null) 
            try 
                JSONObject jsonObj = new JSONObject(jsonStr);
                contacts = jsonObj.getJSONArray(TAG_CONTACTS);

                for (int i = 0; i < contacts.length(); i++) 
                    JSONObject c = contacts.getJSONObject(i);
                    String id = new String(c.getString("id").getBytes("ISO-8859-1"), "UTF-8");
                    String dates = new String(c.getString("dates").getBytes("ISO-8859-1"), "UTF-8");
                    String price = new String(c.getString("gheymat").getBytes("ISO-8859-1"), "UTF-8");
                    HashMap<String, String> contact = new HashMap<String, String>();
                    contact.put("id", id);
                    contact.put("dates", dates);
                    contact.put("price", price);
                    data.add(contact);
                
             catch (JSONException e) 
                e.printStackTrace();
            catch (UnsupportedEncodingException e) 
                e.printStackTrace();
            
        
        return data;
    

    @Override
    protected void onPostExecute(ArrayList<HashMap<String, String>> result) 
        super.onPostExecute(result);
        if(ladap==null)
            ladap=new ListAdapter(MainActivity.this,result);
            lv.setAdapter(ladap);
        else
            ladap.addAll(result);
            ladap.notifyDataSetChanged();
        
    

【讨论】:

非常感谢您的回复,我将代码更改为您所说的(我用新代码更新了我的问题)。我认为在您的帮助下,最后一个问题得到了解决,但是有一个新问题,在我调用 ladap.addAll(result); 后列表视图没有更新;我登录了,我有 30 个新项目,但它没有向 listView 添加新项目。你能帮我解决这个问题吗?【参考方案2】:

这是错误的

 public void updateList(ArrayList<HashMap<String, String>> list) 
             this.list = list;
             notifyDataSetChanged();
        

这也是错误的

if (!isCancelled() && goterr == false) 
            ListAdapter ladap=new ListAdapter(MainActivity.this, contactList);
            lv.setAdapter(ladap);
            ladap.notifyDataSetChanged();
            //ladap.updateList(contactList);
    

您可以做的不是创建一个新的适配器,而是将数据添加到您在上面创建的以前的适配器

ListAdapter ladap

【讨论】:

谢谢你的回复,我把你说的第一部分代码去掉,第二部分你说错了,应该换成什么? 将其添加到您的适配器,然后在完成后通知您的适配器数据集已更改或数据集无效:) 设置适配器后,继续使用相同的适配器,使用 ArrayAdapter 而不是 BaseAdapter 扩展您的适配器。 see this 2.3. ListView example with ArrayAdapter 感谢您的回复,我更新了我的代码,但仍然收到此错误。你能帮我一个忙,看看我的新代码。也许你能帮我解决这个烦人的问题。谢谢【参考方案3】:

好的,所以如果你只想创建一个适配器就可以了,在 asyc 任务结束时执行,否则让它成为一个成员并在 onCreate 或类似的东西中启动它。

从技术上讲,如果您替换列表的所有内容,那么您的方法很好,替换 ArrayList,但不要忘记调用 adapter.notifyDataSetChanged()。

但是,如果您只更改列表的某些内容,例如您添加新元素或删除元素,那么您应该对原始 ArrayList 执行这些更改,然后调用 adapter.notifyDataSetChanged()。

注意,所有对 adapter.notifyDataSetChanged() 的调用都应该在 UI 线程上完成。

另外,据我所知,如果这是您正在运行的确切代码,则不应出现此错误,似乎该错误是从另一个地方生成的。

【讨论】:

感谢您的回复,我更新了我的代码,但仍然收到此错误。你能帮我一个忙,看看我的新代码。也许你能帮我解决这个烦人的问题。谢谢 尝试在 Activity onCreate 中创建适配器,例如这些行: ladap=new ListAdapter(MainActivity.this,result); lv.setAdapter(ladap); 也可能与 AsyncTask 和内存泄漏有关,但如果没有完整的调试功能,我不能肯定【参考方案4】:
if (!isCancelled() && goterr == false) 
        ListAdapter ladap=new ListAdapter(MainActivity.this, contactList);
        lv.setAdapter(ladap);
        ladap.notifyDataSetChanged();
        //ladap.updateList(contactList);

错了。

应该是

if (!isCancelled() && goterr == false) 
        ladap.addAll(contactList);
        ladap.notifyDataSetChanged();

您应该只定义一次适配器并相应地更新其中的值。 You can use various constructors to suit your requirements.

----------已编辑----------

if (!isCancelled() && goterr == false) 
            if(ladap==null)
                ladap=new ListAdapter(MainActivity.this, contactList);
                lv.setAdapter(ladap);
                ladap.addAll(contactList);

            else
                ladap.addAll(contactList);


    

public void addAll(ArrayList<HashMap<String, String>> contactList) 
thislist.clear();       
 this.list = contactList;
        notifyDataSetChanged();
    

【讨论】:

感谢您的回复,我更新了我的代码,但仍然收到此错误。你能帮我一个忙,看看我的新代码。也许你能帮我解决这个烦人的问题。谢谢 thislist.clear();清除数据,我的意思是,在实现这一行之后,listview 是空的,什么都没有检索到。 protected Void doInBackground(Void... arg0) 什么也不返回。要获取数据,您需要从 doInBackground() 方法返回。然后使用该数据更新联系人列表视图。问题是绑定到适配器的 ArrayList 在后台线程中发生了更改。您的适配器实际上是从后台线程修改的,正如异常所建议的那样。解决方案是将其移至 UI 线程。检查@Haresh Chhelana 答案。 感谢您的回复,我将代码更改为您所说的(我用新代码更新了我的问题)。我认为最后一个问题已解决,但有一个新问题,在我调用 ladap.addAll(result); 后列表视图没有更新;我登录了,我有 30 个新项目,但它没有向 listView 添加新项目。你能帮我解决这个问题吗?

以上是关于android -BaseAdapter 不会向 listView 添加新项目的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 上向用户付款

推送通知不会在 Android 上弹出

Android:PagerAdapter 删除最后一个视图,因此您无法向左滑动

WearableListenerService onMessageReceived 不会被解雇 [android wear]

如果 Android 设备长时间处于空闲状态,则不会收到推送通知

Android向系统日历添加日程提醒事件