【问题标题】:Android refreshing adapter work after rotation again device再次旋转设备后Android刷新适配器工作
【发布时间】:2017-10-09 04:40:22
【问题描述】:

当我将一些数据添加到“列表模型”并恢复旋转设备上保存的数据时,此代码工作正常,不幸的是,在恢复数据并将其设置为onRestoreInstanceState 方法中的model 之后,在添加其他数据后,适配器无法用新添加的数据刷新,适配器中的数据源可以更新,但适配器不知道它们,我正在使用MVVM数据模型绑定并搜索更多关于这个问题的时间无法解决。

Rhat 有一个简单的提示,在旋转再次设备后,我的适配器可以使用所有添加的数据进行刷新,而适配器不会刷新。

public class ActivityRegister extends BaseActivities{
    private  List<RobotViewModel> model  = new ArrayList<>();
    ...
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ...
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putParcelable("model", Parcels.wrap(model));
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle outState) {
        model = Parcels.unwrap(outState.getParcelable("model"));

        adapter.setData(model);
        adapter.notifyItemInserted(model.size() - 1);
        binding.registerRobot.scrollToPosition(adapter.getItemCount() - 1);
    }

添加到model方法:

    @Override
    public void clickOnSendCommandToRobot() {
        RobotViewModel temp = new RobotViewModel();

temp.setMessage("message");

        temp.setCommand(true);

        model.add(temp);

        adapter.notifyItemInserted(model.size() - 1);
        binding.registerRobot.scrollToPosition(adapter.getItemCount() - 1);
    }

我的适配器类:

public class RobotMessagesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<RobotViewModel> list;
    private LayoutInflater       inflater;

    public RobotMessagesAdapter(List<RobotViewModel> robotViewModels) {
        this.list = robotViewModels;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (inflater == null) {
            inflater = LayoutInflater.from(parent.getContext());
        }
        if (viewType == SV.RobotMessageType.SENT_BY_USER.ordinal()) {
            return new UserViewHolder(UserMessagesDataBinding.inflate(inflater, parent, false));
        } else {
            return new RobotViewHolder(RobotDataBinding.inflate(inflater, parent, false));
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        switch (getItemViewType(position)) {
            case 0:
                ((UserViewHolder) holder).bind(list.get(position));
                break;
            case 1:
                ((RobotViewHolder) holder).bind(list.get(position));
                break;
        }
    }

    ...

    public void setData(List<RobotViewModel> data) {
        Log.e("data size ", data.size() + "");
        list.clear();
        list.addAll(data);
    }
}

我想知道为什么这段代码可以正常工作:

    @Override
    protected void onRestoreInstanceState(Bundle outState) {
        model = Parcels.unwrap(outState.getParcelable("model"));

        adapter.setData(model);
        adapter.notifyItemInserted(model.size() - 1);
        binding.registerRobot.scrollToPosition(adapter.getItemCount() - 1);

        RobotViewModel temp = new RobotViewModel();

temp.setMessage("message");

        temp.setCommand(true);

        model.add(temp);

        adapter.notifyItemInserted(model.size() - 1);
        binding.registerRobot.scrollToPosition(adapter.getItemCount() - 1);
    }

没有任何问题,在移动这行之后:

        RobotViewModel temp = new RobotViewModel();

temp.setMessage("message");

        temp.setCommand(true);

        model.add(temp);

        adapter.notifyItemInserted(model.size() - 1);
        binding.registerRobot.scrollToPosition(adapter.getItemCount() - 1);

到其他不起作用的方法:|

我的主持人:

public class ActivityRegisterPresenter {
    private ActivityRegisterContract view;

    public ActivityRegisterPresenter(ActivityRegisterContract mView) {
        view = mView;
    }

    ...
}

还有我的 ViewModel:

public class ActivityRegisterViewModel extends BaseObservable {
    private String readContactPermission;
    private String getMessages;

    public ActivityRegisterViewModel() {
    }

    @Bindable
    public String getReadContactPermission() {
        return readContactPermission;
    }

    public void setReadContactPermission(String readContactPermission) {
        this.readContactPermission = readContactPermission;
        notifyChange();
    }

    public String getGetMessages() {
        return getMessages;
    }

    public void setGetMessages(String getMessages) {
        this.getMessages = getMessages;
    }
}

SOURCE CODE IS HERE

问题出在clickOnRegisterMobileNumberclickOnSendCommandToRobot 方法中

【问题讨论】:

  • 所以旋转是问题所在?
  • @Remario 在更改设备旋转并使用clickOnSendCommandToRobot 方法添加更多项目后。我在适配器上看不到它们,但再次旋转设备后,我在适配器上看到它们
  • @Remario 我的帖子已更新
  • 好吧,给我一些时间,很快就会给出答案!
  • @Remario 非常感谢,你想和我一起获取源代码吗?

标签: android mvvm


【解决方案1】:

我的问题解决了,

将下面这一行添加到您设置适配器的特定活动的清单中

android:configChanges="screenSize|orientation|screenLayout" 

但如果您同时设计纵向和横向布局或仅在这两种模式中的一种模式下运行应用程序,它将返回最佳视图。

【讨论】:

    【解决方案2】:
    The main reason is that, because you called set-data and that method did not immediately notify that the data set was changed, therefore it was not ware.
    
          public void setData(List<RobotViewModel> data) {
                Log.e("data size ", data.size() + "");
                list.clear();
                list.addAll(data);
            }
    
         public void setData(List<RobotViewModel> data) {
                Log.e("data size ", data.size() + "");
    
                list.clear();
                notifyDataSetChanged(); //here,to signal change occurred.
                list.addAll(data);
                notifyDataSetChanged(); //here,to signal change occurred.
    
            }
    
    should probably get into the habit of notifying changes on the spot.
    

    主要问题是,您从未通知您所做的更改,您清除了它,但您从未告诉它,您知道,但适配器不知道,您还使用addAll 插入了新数据但您仍然这样做不通知它。

    【讨论】:

    • 另一个原因是你使用了list.addAll(data);,但是你没有清理也没有删除之前的模型数据。我认为您的意思是在现有条目中添加一个条目!
    • 问题是通知适配器在旋转设备setData 后将新保存的数据更新到model 以进行微调并刷新我的适配器,但是在将更多数据添加到model 之后,例如单击按钮无法通知我的适配器更新新数据,根本无法刷新,使用setData点击方法导致清除适配器上的所有数据
    • 不幸的是问题没有解决先生,你可以测试这个项目ufile.io/g351w问题在clickOnRegisterMobileNumber方法和clickOnSendCommandToRobot
    • @Remario:notifyDataSetChanged()应该在数据编辑之后调用,所以在list.addAll(data)之后。我错了吗?
    • 是的,这是正确的,这是基于状态的内部实现。当您将数据放入其中时,它会缓存并记住该数据状态,如果发生某些事情并且您没有通知它更改,它不会知道状态已更改。
    【解决方案3】:

    我尝试了您的代码,它只需很少的更新就可以正常工作。 当您执行此操作时

     model.add(temp);
     adapter.notifyItemInserted(model.size() - 1);
    

    您假设对象模型和适配器数据源之间的链接是持久的。 这个假设是错误的,其实只要把上面的代码替换成

     model.add(temp);
     adapter.setData(model);
     adapter.notifyItemInserted(model.size() - 1);
    

    它工作正常。 我希望它有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-21
      • 2020-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多