代码之家  ›  专栏  ›  技术社区  ›  Jeff

由于ArrayList到适配器绑定问题,notifyDataSetChanged()无法正确更新

  •  1
  • Jeff  · 技术社区  · 7 年前

    我读过以下内容:

    ArrayList not updating after using .clear()
    notifydataSetChanged working but only showing 1 result in listview Android
    notifyDataSetChanged() does not affect my adapterView
    Android: notifyDataSetChanged(); not working
    notifydatasetchanged() not working after onbackpressed()
    Android notifyDataSetChanged not working
    Android notifyDataSetChanged() not working

    仍然无法从新数据集更新我的适配器。

    我的密码 调试模式 详情如下:

    public class PetInformationActivity extends AppCompatActivity
    implements ConfirmDialogFragment.ConfirmDialogListener, MedicalInformationFragment.OnFragmentInteractionListener{
    
    private static List<Assignment> listAssignments = new ArrayList<>();
    private static AssignmentsAdapter mAdapter;
    private static PetInformationViewModel sPetInformationViewModel;
    .
    .
    .
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
    .
    .
    .
    /**
    * get the providers' IDs assigned to the pet: fillAssignmentsArray()
    */
    listAssignments = sPetInformationViewModel.getAssignedProviders(petId);
    

    此时在调试中:
    mAdapter=null
    列表分配=(ArrayList@5411)大小=0

    Log.d(TAG, "listAssignments has " + listAssignments.size() + " Assignment objects in it");  
    Log.d(TAG, "listAssignments is: " + listAssignments);   
    

    此时在调试中:
    mAdapter=null
    列表分配=(ArrayList@5461)尺寸=1
    0 = (Assignment@5496)“作业{mType='Veterinarian',mProviderName='red 兽医“}”

    mAdapter = new AssignmentsAdapter(this, listAssignments);   
    

    此时在调试中:
    mAdapter=(AssignmentsAdapter@5499)
    列表分配=(ArrayList@5461)大小 = 1
    0 = (Assignment@5496)“作业{mType='Veterinarian',mProviderName='red vet'}”

    mRecyclerView.setAdapter(mAdapter);
    .
    .
    .
    }
    
    public void onResume(){
    super.onResume();
    Log.d(TAG, "Entered: onResume");
    listAssignments.clear();
    Log.d(TAG, "listAssignments is: " + listAssignments);
    

    此时在调试中:
    mAdapter=(AssignmentsAdapter@5499)
    列表分配=(ArrayList@5461)大小 = 0**

    listAssignments = sPetInformationViewModel.getAssignedProviders(petId);
    Log.d(TAG, "listAssignments is: " + listAssignments);
    

    此时在调试中:
    mAdapter=(AssignmentsAdapter@5499)
    列表分配=(ArrayList@5594)大小 = 1
    0 = (Assignment@5607)“作业{mType='Veterinarian',mProviderName='red vet'}”

    mAdapter.notifyDataSetChanged();
    }  
    

    此时,屏幕应显示中所示的文本,但屏幕为空白Assignment@5607.notififyDataSetChanged()似乎通知mAdapter更改了onCreate中显示的文本(ArrayList@5461)在简历中清除(ArrayList@5461)但对于onResume中对数据的新调用,情况并非如此(ArrayList@5594).

    这似乎表明,当mAdapter被初始化为listAssignments时,它被设置为使用地址为@5461的ArrayList。当在onResume中调用新数据时,在a)使用后退按钮返回和(b)此活动首次启动时,会在不同的地址创建一个新的ArrayList。

    因此,我似乎没有正确地合并我的ArrayList,因为对listAssignments的所有更新都会产生一个全新的ArrayList对象,该对象永远不会用于更新mAdapter,它将始终更新为地址为@5461的初始ArrayList。

    我已经搜索了有关如何将适配器正确绑定到ArrayList的信息,但没有找到比我所做的更多的内容。我假设notifyDataSetChanged()的目的是使用现有适配器进行更新,这样就不必销毁现有适配器,并在每次数据集更改时创建一个新适配器,如下所示:

    notifyDataSetChanged() fails to update adapter onClick

    2 回复  |  直到 7 年前
        1
  •  0
  •   pnavk    7 年前

    传递给ArrayAdapter的引用与此处指定的引用不同:

    listAssignments = sPetInformationViewModel.getAssignedProviders(petId);
    

    就ArrayAdapter而言,它所引用的listAssignments在Resume上已被清除,并且从未向其添加任何内容。它对新的listAssignments引用一无所知。

    尝试这样做:

    public void onResume()
    {
        super.onResume();
        Log.d(TAG, "Entered: onResume");
        listAssignments.clear();
        Log.d(TAG, "listAssignments is: " + listAssignments);
        List<Assignment> newList = sPetInformationViewModel.getAssignedProviders(petId);
        listAssignments.addAll(newList);
        mAdapter.notifyDataSetChanged();
    }
    
        2
  •  0
  •   Jeff    7 年前

    好吧,我在这里冒险说notifyDataSetChanged()不适用于ArrayList,因为每次加载时它的地址都会发生变化,请查看我在pnavk上的原始帖子和评论以查看详细信息。据我了解,java没有提供一种方法来将一个数组列表的地址设置成C或C++通过指针进行的操作,因此适配器被设置为原始的ARARYLIST对象的一个内存位置,因此在每个NoTIFYDATETETROUNDE()调用中指向相同的数据,即使java已经为该ARARYLIST对象使用了新的内存位置,或者创建了一个同名的全新ArrayList对象。

    因此,我从ArrayList中的新数据集更新RecyclerView的答案是将onResume中的适配器重置为新适配器,然后将该适配器重新分配给你的RecyclerView,正如我在回复pnavk时提到的:

    mAdapter = new AssignmentsAdapter(this, listAssignments); 
    mRecyclerView.setAdapter(mAdapter);