Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android refreshing adapter work after rotation again device

Tags:

android

mvvm

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

like image 846
tux-world Avatar asked May 10 '17 13:05

tux-world


2 Answers

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.

like image 188
tux-world Avatar answered Nov 09 '22 16:11

tux-world


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.

like image 27
Remario Avatar answered Nov 09 '22 15:11

Remario