Android refreshing adapter work after rotation aga

2020-02-12 02:47发布

问题:

This code works fine when i add some data into 'List model' and restore saved data on rotation device, unfortunately after restore data and set that to model within onRestoreInstanceState method, after adding other data to that, adapter could not refresh with new added data, data source in adapter after can be updated, but adapter can;t know them , I'm using MVVM data model binding and search more time about this problem i can't resolve that.

Rhat have a simple tip which after rotation again device, my adapter can be refresh with all added data which adapter don't refresh with them.

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

add to model method:

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

My Adapter Class:

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

I'm wondering why this code work fine:

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

without any problem and after move this lines:

        RobotViewModel temp = new RobotViewModel();

temp.setMessage("message");

        temp.setCommand(true);

        model.add(temp);

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

to other method that doesn't work :|

My presenter:

public class ActivityRegisterPresenter {
    private ActivityRegisterContract view;

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

    ...
}

and my 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

problems are in clickOnRegisterMobileNumber and clickOnSendCommandToRobot methods

回答1:

My problem resolved,

after adding this below line into manifest for specific activity where you setAdapter

android:configChanges="screenSize|orientation|screenLayout" 

But it will return best view if you design Both Portrait and Landscape layout or running app only in one mode of these both.



回答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.

The main problem is this, you never notified the changes you made, you cleared it , but you never told it, you know, bu the adapter does not know, also you inserted fresh data with addAll but you still did not notify it.



回答3:

I tried your code and it works just fine with few updates. When you perform this action

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

You are assuming the persistence of the link between the object model and the adapter datasource. This assumption is wrong, in fact if you just replace the code above with

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

it works fine. I hope it helped.



标签: android mvvm