在一个片段中更新RecyclerView,在按钮上单击另一个片段

时间:2019-09-03 11:52:49

标签: android android-fragments android-recyclerview

有两个片段,PointCoordinates和PointslistFragment。 PointCoodrinates将输入作为点名称,并从用户处获取x,y坐标。并且当用户单击PointCoordinates中的“保存”按钮时,应该更新PointsListFragment中的recyclerview。MainActivity containing PointListFragment and pointCoordinatesOn clicking new, moves to the next fragment to enter PointCoordinates

我创建了一个接口,该接口包含指向点列表和点的getcount方法的addpoint。该接口在PointslistFragment中实现。并为pointsList创建和适配器。我被困在如何将连接从一个片段转移到另一个片段以及何时调用notifyDataChanged()的问题上。

接口:

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

3 个答案:

答案 0 :(得分:1)

我建议fragment之间共享ViewModel。最初,视图模型实例将通过活动创建,该活动是片段的容器。然后使用活动上下文,其他片段将观察相同的视图模型可变数据。 请参阅下面的链接

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

答案 1 :(得分:0)

您可以为此目的使用EventBus,只需创建如下所示的类

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

注册和取消注册以下事件

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

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

在按钮上单击后发布事件,如下所示:

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

获取数据:

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

答案 2 :(得分:0)

我认为您的代码将无法正常工作,主要思想是您尝试在不知道片段实际状态的情况下将数据从一个片段传输到另一个片段。它可能导致找不到视图的多个NullPointerExceptions。为避免这种情况,我建议您将数据传输到活动中,在其中显示PointCoodrinates,并显示片段PointslistFragment。然后将Point转移到它。这是我应该这样做的方式:

主要:

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

如果您读懂代码,您将了解所有内容。我尝试使用尽可能多的数据来传输数据,在这里您可以找到Activity Lifecycle,Bundles,Interfaces,Adapters和Listeners的用法。希望对您有帮助。如果您有任何疑问,我随时在这里回答,但是请您自己理解。