Giorgi Abashidze
Giorgi Abashidze

Reputation: 55

Android - Observing on live data not working from fragment

I have 2 fragment in activityty a list fragment and details fragment,details fragment showing selected items details from list fragment and there is button to change list item "status" set order as ready.

I want to move selected item to ready seaction when button Order is ready clicked.

I tried it with observing with shared view model but onchange method not calling when I set value in it.

enter image description here

here is a viewModel:

package com.example.ordermanager.fragments;
import android.database.ContentObserver;
import android.os.Handler;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import com.example.ordermanager.fragments.orderlist.dummy.DummyContent;

import java.util.List;

public class SharedViewModel extends ViewModel {

    private MutableLiveData<DummyContent.DummyItem> item = new MutableLiveData<DummyContent.DummyItem>();

    public void setItem(DummyContent.DummyItem value){
        item.setValue(value);
    }

    public MutableLiveData<DummyContent.DummyItem> getItem(){
        return item;
    };

}

ListFragment:

public class OrderItemFragment extends Fragment {

    // TODO: Customize parameter argument names
    private static final String ARG_COLUMN_COUNT = "column-count";
    // TODO: Customize parameters
    private int mColumnCount = 1;
    private OnListFragmentInteractionListener mListener;
    private SharedViewModel vm;
    private RecyclerView recyclerView;

    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public OrderItemFragment() {
    }

    // TODO: Customize parameter initialization
    @SuppressWarnings("unused")
    public static OrderItemFragment newInstance(int columnCount) {
        OrderItemFragment fragment = new OrderItemFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_COLUMN_COUNT, columnCount);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments() != null) {
            mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
        }

        vm = ViewModelProviders.of(this).get(SharedViewModel.class);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_order_item_list, container, false);

        // Set the adapter
        if (view instanceof RecyclerView) {
            Context context = view.getContext();
            recyclerView = (RecyclerView) view;
            if (mColumnCount <= 1) {
                recyclerView.setLayoutManager(new LinearLayoutManager(context));
            } else {
                recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
            }

            recyclerView.setAdapter(new MyOrderItemRecyclerViewAdapter(DummyContent.ITEMS, mListener));
        }


        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Observer<DummyItem> itemObserver = new Observer<DummyItem>() {
            @Override
            public void onChanged(@Nullable DummyItem selectedItem) {
                //this never happening
                Log.e("hereeeee","dfgdfg");
                recyclerView.getAdapter().notifyDataSetChanged();
            }
        };

        vm.getItem().observe(this, itemObserver);
    }



    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnListFragmentInteractionListener) {
            mListener = (OnListFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnListFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p/>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */


    public interface OnListFragmentInteractionListener {
        // TODO: Update argument type and name
        void onListFragmentInteraction(DummyItem item);
    }
}

DetailsFragment:

public class OrderDetailFragment extends Fragment {

    private SharedViewModel mViewModel;
    private DummyContent.DummyItem selectedItem;
    private Button ReadyBtn;

    public static OrderDetailFragment newInstance() {
        return new OrderDetailFragment();
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.order_detail_fragment, container, false);

        Bundle bundle = getArguments();

        if(bundle != null){
                selectedItem = (DummyContent.DummyItem)getArguments().getSerializable("item");

                TextView tv = (TextView) view.findViewById(R.id.detailid);
                tv.setText(selectedItem.content);

        }
        ReadyBtn = view.findViewById(R.id.readyBtn);
        ReadyBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(selectedItem != null){
                    selectedItem.isReady = true;
                    mViewModel.getItem().setValue(selectedItem);
                }
            }
        });

        return view;
    }



    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mViewModel = ViewModelProviders.of(this).get(SharedViewModel.class);

    }

}

Observer is in ListFragment OnViewCreated function

Any Ideas?

Upvotes: 0

Views: 7186

Answers (2)

aLT
aLT

Reputation: 326

You should change the data in your adapter before calling notifyDataSetChanged() method. Now you are getting new value in itemObserver but you're not changing the adapter.

UPD. I've solved the problem! The key in your initialization code of SharedViewModel. You should attach activity to the ViewModelProviders class in both cases, but you use this and in reality you have two different instances instead of one which should be attached to the parent activity. So, change the code of initialization to mViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); and it'll work!

Upvotes: 2

Spidey
Spidey

Reputation: 974

When you declare local variables in functions, they get destroyed when the function call ends. Therefore you need to store your itemObserver in a field.

On a side note...
You don't need a default empty constructor in fragments unless you create a custom one, which isn't recommended.

Regarding recyclerview I would recommend reading this in detail (especially the ListAdapter part).

Upvotes: 0

Related Questions