【问题标题】:adapter.notifyDataSetChange() not updating the listview after returning from another activityadapter.notifyDataSetChange() 从另一个活动返回后不更新列表视图
【发布时间】:2016-06-03 11:06:56
【问题描述】:

我有两个活动:1. 包含列表视图 (Activity1),2. 列表视图中每一行的详细信息 (Activity2)。

当用户单击 Activity1 中列表视图的任何一行时,其各自的详细信息会显示在 Activity2 中,即 Activity2 已启动。当用户在 Activity2 中编辑一些细节时,所有更改都会保存到服务器,当我返回 Activity1 时,我正在从服务器获取新的(更新的)列表并想要更新 Activity1 的 UI(列表视图)。但这不会发生。我正在执行以下操作来更新列表视图:

@Override
protected void onStart() {
    super.onStart();
    Toast.makeText(this, "onStart", Toast.LENGTH_LONG).show();
    PetService petService = FactoryMaker.getFactory(AppConstants.PET_SERVICE).getPetServiceImpl(AppConstants.PARSE_IMPL, this);
    //pets = petService.getPetList();
    //adapter = new PetListArrayAdapter(getApplicationContext(),R.layout.pet_list_item, pets);
    //petListView.setAdapter(adapter);

    pets = petService.getPetList();
    adapter.clear();
    adapter.addAll(pets);
    adapter.notifyDataSetChanged();

    if(pets.size()>0) {
        retrieve.setVisibility(View.INVISIBLE);
    }else{
        retrieve.setVisibility(View.VISIBLE);
    }
}

但是,如果我再次设置适配器(就像我注释掉的三行),列表视图会根据需要更新,但使用 notifyDataSetChanged(),它不起作用。我已经关注了这个问题的所有问题,但似乎没有任何效果。我的适配器从 ArrayAdapter 扩展而来。请帮忙!

我的适配器实现:

public class PetListArrayAdapter extends ArrayAdapter<Pet> {

     private final String TAG="PetListArrayAdapter";

     private List<Pet> pets = null;
     private Context applicationContext =null;

     public PetListArrayAdapter(Context context, int resource, List<Pet> petList) {
          super(context, resource, petList);
          pets = petList;
          applicationContext = context;
     }

     @Override
     public int getCount(){
          int size = 0;
          if(pets!=null) {
             size = pets.size();
          }
          return size+1;
     }

     @Override
     public int getItemViewType(int position) {
          return (position == 0) ? 0 : 1;
     }

     @Override
     public int getViewTypeCount() {
          return 2;
     }


     @Override
     public View getView(int position, View convertView, ViewGroup parent)  {
         Log.d(TAG, "getView for position" + position);
         int type = getItemViewType(position);
         LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         if(convertView==null) {
              if(type==1) {
                  convertView = inflater.inflate(R.layout.pet_list_item, null);
                  TextView t = (TextView)convertView.findViewById(R.id.petName);
                  final Pet pet = pets.get(position-1);
                  Log.d(TAG, "pet:" + pet);
                  t.setText(pet.getName());

                  ImageView petImage =(ImageView)convertView.findViewById(R.id.petImage);

                  String imageUrl = pet.getThumbnailUrl();
                  //if(petImage.getDrawable()==null) {
                  if (imageUrl != null) {
                       Log.d(TAG, "Loading Image for position" + position);
                       new ImageDownloader(petImage).execute(imageUrl);
                  }
             /*}else{
             Log.d(TAG, "Image present for position" + position);
             }*/
          }else if (type==0){
               convertView = inflater.inflate(R.layout.add_pet, null);
          }
       }

       return convertView;
   }
}

【问题讨论】:

  • 首先,请求是在后台线程还是ui线程?其次,什么是适配器实现,你能展示一下吗?
  • 请求在 UI 线程上。
  • 如何在 UI 线程上向服务器发出请求我不明白。
  • @AndreiT 我在后端使用 Parse 云。为了从中获取数据,我使用了 ParseQuery.find() ,它确实阻塞了解析文档中所写的调用线程,并且我从主线程调用它。
  • 调试应用,看看你添加的值和你拥有的值是否有差异。

标签: android listview adapter notifydatasetchanged


【解决方案1】:

试试

pets.clear();
pets.addAll(petService.getPetList());
adapter.notifyDataSetChanged();

我猜适配器列表失去了与实际列表的链接。

【讨论】:

  • 不,它不起作用。该列表仍未更新。
【解决方案2】:

在简历中添加您的获取代码

@Override
    protected void onResume() {
        super.onResume();

        pets = petService.getPetList();
        adapter.clear();
        adapter.addAll(pets);
        adapter.notifyDataSetChanged();

        if(pets.size()>0) {
            retrieve.setVisibility(View.INVISIBLE);
        }else{
            retrieve.setVisibility(View.VISIBLE);
        }
    }

【讨论】:

    【解决方案3】:
    1. 首先,使用 startActivityForResult(intent,requesCode) 而不是 startActivity(intent) 方法启动 Activity2。
    2. 覆盖/实现 Activity1 的 onActivityResult(int requestCode, int resultCode, Intent data) 并执行这些代码。这将确保 onBackPressed 您的列表得到更新

      pets.clear(); 宠物.addAll(petService.getPetList()); 适配器.notifyDataSetChanged();

    所以你的代码看起来像

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //...some codes
    
        pets.clear();
        pets.addAll(petService.getPetList());
        adapter.notifyDataSetChanged();
    
    }
    

    【讨论】:

      【解决方案4】:


      我用这个适配器进行了测试,它对我有用。然而, 我没有附加图片,但它应该可以正常工作。

      public class CustomArrayAdapter extends ArrayAdapter<Pet> {
          private final String TAG = "PetListArrayAdapter";
      
          private List<Pet> pets = null;
      
          public CustomArrayAdapter(Context context, List<Pet> petList) {
               super(context, 0, petList);
               pets = petList;
          }
      
          @Override
          public int getCount() {
              int size = 0;
              if (pets != null) {
                  size = pets.size() + 1;
              }
              return size;
          }
      
          @Override
          public int getItemViewType(int position) {
               return (position == 0) ? 0 : 1;
          }
      
          @Override
          public int getViewTypeCount() {
               return 2;
          }
      
      
          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
               Log.d(TAG, "getView for position" + position);
               ViewHolder holder;
               int type = getItemViewType(position);
               LayoutInflater inflater = LayoutInflater.from(getContext());
               if (convertView == null) {
                   holder = new ViewHolder();
                   if (type == 1) {
                       convertView = inflater.inflate(R.layout.list_item_layout, null);
                       holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
                       holder.tvDescription = (TextView) convertView.findViewById(R.id.tv_descriotion);
                       final Pet pet = pets.get(position - 1);
                       Log.d(TAG, "pet:" + pet);
      
                      convertView.setTag(holder);
                   } else if (type == 0) {
                        convertView = inflater.inflate(R.layout.list_add_layout, null);
                        holder.tvName = (TextView) convertView.findViewById(R.id.tv_add);
                   }
              } else {
                   holder = (ViewHolder) convertView.getTag();
              }
              if (holder != null) {
                   if (type == 1) {
                       holder.tvName.setText(pets.get(position - 1).getName());
                       if (holder.tvDescription != null) {
                          holder.tvDescription.setText(pets.get(position - 1).getDescription());
                       }
                   } else if (type == 0) {
                       holder.tvName.setText("Add new pet");
                   }
               }
      
               return convertView;
           }
           static class ViewHolder {
               TextView tvName;
               TextView tvDescription;
           }
       }
      

      我必须补充一点,您需要有一个合适的支架来处理添加宠物的布局和 宠物的布局。我在这里添加的只是你的一个起点。 我会创建包含一个 textview 或什么都没有的基本持有人,并为特定类型使用特定持有人,并且只要它是类型 1 或 0,您就可以转换为正确的持有人。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多