krishna sree
krishna sree

Reputation: 63

Update RecyclerView in one fragment, on button click in other fragment

There are two fragments, PointCoordinates and PointslistFragment. PointCoodrinates takes input as point name and x, y coordinates from the user. And when user clicks save button in PointCoordinates the recyclerview in PointsListFragment should be updated.MainActivity containing PointListFragment and pointCoordinates. On clicking new, moves to the next fragment to enter PointCoordinates

I have created an interface which contains methods addpoint to the points list and getcount of the points. This interface is implemented in PointslistFragment. And created and adapter for pointsList. I am stuck at how the transfer of the connection from one fragment to another happens and when the notifyDataChanged() should be called.

Interface:

public interface IPointOperations {
    public void addPoint(Point point);
    public int getPointCount();
}

PointsListFragment:

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

        pointListAdapter = new PointListAdapter(pointList);
        View view = inflater.inflate(R.layout.fragment_points_list, container, false);
        RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        setListener(this);
        recyclerView.setAdapter(pointListAdapter);
        return view;
    }

    @Override
    public void addPoint(Point point) {
        pointsList.add(point);
        pointListAdapter.notifyDataSetChanged();
    }

    @Override
    public int getPointCount() {
        return pointList.size();
    }

PointCoordinates:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        View view = inflater.inflate(R.layout.fragment_point_coordinates, container, false);
        e1 = view.findViewById(R.id.xValue);
        e2 = view.findViewById(R.id.yValue);
        e3 = view.findViewById(R.id.name);
        button = view.findViewById(R.id.enterButton);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                double x = Double.parseDouble(e1.getText().toString());
                double y = Double.parseDouble(e2.getText().toString());
                String name = e3.getText().toString();
                point = new Point(x, y, name);
                iPointOperations.addPoint(point);
            }
        });
        return view;
    }

    public void setListener(IPointOperations iPointOperations){
        this.iPointOperations = iPointOperations;
    }

Upvotes: 0

Views: 590

Answers (3)

Farrukh Nabiyev
Farrukh Nabiyev

Reputation: 366

I think your code will not work, main idea is that you try to transfer data from one fragment to another without knowing the actual state of the fragment. It can lead to multiple NullPointerExceptions of view could not be found. To avoid this I advice you to transfer data to your Activity in which you show your PointCoodrinates, show your fragment PointslistFragment. and then transfer Point to it. Here is how I ought to do that:

Main:

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;

import android.os.Bundle;
import android.view.View;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

public class MainActivity extends AppCompatActivity {

    private FloatingActionButton fab;
    private PointslistFragment pointslistFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fab = findViewById(R.id.fab_add);

        pointslistFragment = new PointslistFragment();

        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.add(R.id.main_container, pointslistFragment);
        ft.commit();

    }

    @Override
    protected void onStart() {
        super.onStart();

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                final PointCoordinates pointCoordinates = new PointCoordinates();
                pointCoordinates.setListener(new PointCoordinates.CallbackPointCoordinates() {
                    @Override
                    public void getPoint(Point point) {

                        Bundle bundle = new Bundle();
                        bundle.putSerializable("point", point);
                        pointslistFragment.setArguments(bundle);
                        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                        ft.replace(R.id.main_container, pointslistFragment);
                        ft.commit();
                    }
                });
                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                ft.replace(R.id.main_container, pointCoordinates);
                ft.addToBackStack(null);
                ft.commit();

            }
        });

    }
}

PointCoordinates:

package com.example.myapplication;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class PointCoordinates extends Fragment {

    private EditText e1, e2, e3;
    private Button button;
    private Point point;
    private CallbackPointCoordinates callbackPointCoordinates;

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

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

        e1 = view.findViewById(R.id.xValue);
        e2 = view.findViewById(R.id.yValue);
        e3 = view.findViewById(R.id.name);
        button = view.findViewById(R.id.enterButton);

        return view;
    }

    @Override
    public void onStart() {
        super.onStart();
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                double x = Double.parseDouble(e1.getText().toString());
                double y = Double.parseDouble(e2.getText().toString());
                String name = e3.getText().toString();
                point = new Point(x, y, name);
                callbackPointCoordinates.getPoint(point);
            }
        });
    }

    public interface CallbackPointCoordinates{

        void getPoint(Point point);

    }

    public void setListener(CallbackPointCoordinates callbackPointCoordinates){
        this.callbackPointCoordinates = callbackPointCoordinates;
    }
}

PointListAdapter:

package com.example.myapplication;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class PointListAdapter extends RecyclerView.Adapter<PointListAdapter.PointViewHolder> {

    private List<Point> pointList;

    PointListAdapter(List<Point> pointList){
        this.pointList = pointList;
    }

    @NonNull
    @Override
    public PointViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.element_rec_view,
                parent, false);

        return new PointViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull PointViewHolder holder, int position) {

        holder.textViewE1.setText(String.valueOf(pointList.get(position).getX()));
        holder.textViewE2.setText(String.valueOf(pointList.get(position).getY()));
        holder.textViewE3.setText(String.valueOf(pointList.get(position).getName()));

    }

    @Override
    public int getItemCount() {
        return pointList.size();
    }

    public class PointViewHolder extends RecyclerView.ViewHolder {

        TextView textViewE1;
        TextView textViewE2;
        TextView textViewE3;

        public PointViewHolder(@NonNull View itemView) {
            super(itemView);

            textViewE1 = itemView.findViewById(R.id.el_e1);
            textViewE2 = itemView.findViewById(R.id.el_e2);
            textViewE3 = itemView.findViewById(R.id.el_e3);

        }
    }
}

PointslistFragment:

package com.example.myapplication;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class PointslistFragment extends Fragment {

    private RecyclerView recyclerView;
    private RecyclerView.Adapter pointListAdapter;
    private RecyclerView.LayoutManager layoutManager;
    private List<Point> pointList = new ArrayList<>();

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

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

        recyclerView = view.findViewById(R.id.recycler_view);

        layoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(layoutManager);

        pointListAdapter = new PointListAdapter(pointList);
        recyclerView.setAdapter(pointListAdapter);

        return view;
    }

    @Override
    public void onResume() {
        super.onResume();

        Bundle bundle = this.getArguments();
        if (bundle != null) {
            Log.d("sss", "a " + bundle.toString());

            if (bundle.getSerializable("point") != null){
                Point newPoint = (Point) bundle.getSerializable("point");
                pointList.add(newPoint);
                pointListAdapter.notifyDataSetChanged();
            }

            this.getArguments().remove("point");
        }

    }

    @Override
    public void onStop() {
        super.onStop();
    }
}

If you get through code you will understand everything. I tried to use as much as possible to transfer data, here you can find usage of Activity Lifecycle, Bundles, Interfaces, Adapters and Listeners. Hope it will help you. If you have questions I am here to answer, but try to unterstand this on your own.

Upvotes: 0

Ashok Kumar
Ashok Kumar

Reputation: 1271

I would recommend shared ViewModel between fragment . Initially view model instance will be created from activity which is container for fragments .Then using activity context other fragments will observe the same view model mutable data. Refer below link

https://developer.android.com/topic/libraries/architecture/viewmodel

Upvotes: 1

Kailash Chouhan
Kailash Chouhan

Reputation: 2386

You can use EventBus for this purpose, just create a class like below

public class ExampleEvent {
Object object

public ExampleEvent (Object object) { // object is whatever data you want to pass
       this.object=object;
   }

public Object getData(){
      return object;
    }
}

Register and unregister events like below

@Override
 public void onStart() {
     super.onStart();
     EventBus.getDefault().register(this);
 }

 @Override
 public void onStop() {
     super.onStop();
     EventBus.getDefault().unregister(this);
 }

Post events on button click like below:

EventBus.getDefault().post(new ExampleEvent());

Get Data:

@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(ExampleEvent event) {
    Object object = event.getData();
    // here you can update adapter and notify
};

Upvotes: 0

Related Questions