java 如何将数据从 Recyclerview 传递到 Fragment

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39420496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 04:21:39  来源:igfitidea点击:

How to pass data from Recyclerview to Fragment

javaandroidandroid-fragmentsandroid-recyclerview

提问by Ahmed Ezzat

I have a recyclerView populated in a Fragment and I want to Launch a new Fragment and pass data from the adapter ,I try to use Bundles but it always give a null value this my Adapter Class

我在 Fragment 中填充了一个 recyclerView,我想启动一个新的 Fragment 并从适配器传递数据,我尝试使用 Bundles 但它总是给我的适配器类一个空值

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
private LayoutInflater inflater;
private List<Information> mList;
private FragmentCommunication mCommunicator;

public RecyclerAdapter(Context context, List<Information> list,FragmentCommunication communication) {
    inflater = LayoutInflater.from(context);
    mList = list;
    mCommunicator=communication;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = inflater.inflate(R.layout.single_row, parent, false);
    MyViewHolder holder = new MyViewHolder(view,mCommunicator);
    return holder;
}

@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {

    final Information current = mList.get(position);
    holder.name.setText(current.name);
    holder.job.setText(current.job);

    FragmentB fragmentB=new FragmentB();
    Bundle bundle=new Bundle();
    bundle.putString("NAME",current.name);
    bundle.putString("JOB",current.job);
    fragmentB.setArguments(bundle);

}

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

public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    TextView name;
    TextView job;
    FragmentCommunication mComminication;

    public MyViewHolder(View itemView, FragmentCommunication Communicator) {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.tv_name);
        job = (TextView) itemView.findViewById(R.id.tv_gob);
        mComminication=Communicator;
        name.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        mComminication.respond(getAdapterPosition());
    }
}

and this is my new Fragment that I want to launch

这是我想要启动的新 Fragment

public class FragmentB extends Fragment {
TextView textview;
TextView textView2;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view= inflater.inflate(R.layout.fragment_b,container,false);

    textview= (TextView) view.findViewById(R.id.tv_name);
    textView2= (TextView) view.findViewById(R.id.tv_job);
    return view;
}

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

    Bundle arguments = getArguments();


        if (arguments!=null){
        String name= arguments.get("NAME").toString();
        String job= arguments.get("JOB").toString();
            textview.setText(name);
            textView2.setText(job);}

}

}

}

this is how I connect Fragment and recyclerview Adapter with interface

这就是我将 Fragment 和 recyclerview Adapter 与接口连接的方式

public interface FragmentCommunication {
void respond(int position);

}

}

and this the Fragment where the recyclerview is populated

这是填充 recyclerview 的 Fragment

public class RecyclerViewFragment extends Fragment {
RecyclerView mRecyclerView;
RecyclerAdapter mRecyclerAdapter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view= inflater.inflate(R.layout.recycler_fragment,container,false);

    mRecyclerView= (RecyclerView) view.findViewById(R.id.recycler);
    mRecyclerAdapter=new RecyclerAdapter(getActivity(),getData(),communication);
    mRecyclerView.setAdapter(mRecyclerAdapter);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

    return view;
}

public static List<Information> getData() {
    List<Information>data=new ArrayList<>();
    String[] names={"ahmed","mohammed"};
    String[] jobs={"sacsd","csscs"};

    for (int i=0;i<names.length;i++){
        Information current=new Information();
        current.name=(names[i]);
        current.job=(jobs[i]);
        data.add(current);
    }
    return data;
}

FragmentCommunication communication=new FragmentCommunication() {
    @Override
    public void respond(int position) {
        FragmentB fragmentB=new FragmentB();
        FragmentManager manager=getFragmentManager();
        FragmentTransaction transaction=manager.beginTransaction();
        transaction.replace(R.id.dumper,fragmentB).commit();
    }

};

}

}

and my mainActivity class is just add the RecyclerViewFragment

而我的 mainActivity 类只是添加了 RecyclerViewFragment

public class MainActivity extends AppCompatActivity {

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

    RecyclerViewFragment fragment=new RecyclerViewFragment();
    FragmentManager manager=getSupportFragmentManager();
    FragmentTransaction transaction=manager.beginTransaction();
    transaction.add(R.id.dumper,fragment).commit();
}

}

}

so what is the right way to launch fragmentB and pass the data from recyclerview Adapter to fragmentB

那么启动 fragmentB 并将数据从 recyclerview Adapter 传递给 fragmentB 的正确方法是什么

回答by Ahmed Ezzat

thank you guys for the answer,I solved the problem using an interface with String values to connect the adapter with the fragment that contains the recyclerview and the other fragment here is what I did exactly : this is the interface

谢谢你们的回答,我使用带有字符串值的接口解决了这个问题,将适配器与包含 recyclerview 的片段连接起来,这里的另一个片段正是我所做的:这就是接口

public interface FragmentCommunication {
    void respond(int position,String name,String job);
}

and this is the adapter

这是适配器

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
    private LayoutInflater inflater;
    private List<Information> mList;
    private FragmentCommunication mCommunicator;

    public RecyclerAdapter(Context context, List<Information> list,FragmentCommunication communication) {
        inflater = LayoutInflater.from(context);
        mList = list;
        mCommunicator=communication;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.single_row, parent, false);
        MyViewHolder holder = new MyViewHolder(view,mCommunicator);
        return holder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {

        final Information current = mList.get(position);
        holder.name.setText(current.name);
        holder.job.setText(current.job);

        FragmentB fragmentB=new FragmentB();
        Bundle bundle=new Bundle();
        bundle.putString("NAME",current.name);
        bundle.putString("JOB",current.job);
        fragmentB.setArguments(bundle);

    }

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

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView name;
        TextView job;
        FragmentCommunication mComminication;

        public MyViewHolder(View itemView, FragmentCommunication Communicator) {
            super(itemView);
            name = (TextView) itemView.findViewById(R.id.tv_name);
            job = (TextView) itemView.findViewById(R.id.tv_gob);
            mComminication=Communicator;
            name.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            mComminication.respond(getAdapterPosition(),mList.get(getAdapterPosition()).name,mList.get(getAdapterPosition()).job);
        }
    }
}

the fragment that contains the recyclerview

包含 recyclerview 的片段

public class RecyclerViewFragment extends Fragment {
    RecyclerView mRecyclerView;
    RecyclerAdapter mRecyclerAdapter;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view= inflater.inflate(R.layout.recycler_fragment,container,false);

        mRecyclerView= (RecyclerView) view.findViewById(R.id.recycler);
        mRecyclerAdapter=new RecyclerAdapter(getActivity(),getData(),communication);
        mRecyclerView.setAdapter(mRecyclerAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        return view;
    }

    public static List<Information> getData() {
        List<Information>data=new ArrayList<>();
        String[] names={"ahmed","mohammed"};
        String[] jobs={"sacsd","csscs"};

        for (int i=0;i<names.length;i++){
            Information current=new Information();
            current.name=(names[i]);
            current.job=(jobs[i]);
            data.add(current);
        }
        return data;
    }

    FragmentCommunication communication=new FragmentCommunication() {
        @Override
        public void respond(int position,String name,String job) {
            FragmentB fragmentB=new FragmentB();
            Bundle bundle=new Bundle();
            bundle.putString("NAME",name);
            bundle.putString("JOB",job);
            fragmentB.setArguments(bundle);
            FragmentManager manager=getFragmentManager();
            FragmentTransaction transaction=manager.beginTransaction();
            transaction.replace(R.id.dumper,fragmentB).commit();
        }

    };

}

this is the fragmentB where I get the Strings from the Adapter

    public class FragmentB extends Fragment {
    TextView textview;
    TextView textview2;
    String name;
    String job;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        name=getArguments().getString("NAME");
        job=getArguments().getString("JOB");

    }

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

        textview= (TextView) view.findViewById(R.id.getName);
        textview2= (TextView) view.findViewById(R.id.getJob);
        textview.setText(name);
        textview2.setText(job);


        return view;

    }


}

回答by pz64_

If you are working with kotlin, the solution is much simpler. Original Answer here

如果您使用 kotlin,解决方案要简单得多。 原答案在这里

pass the function val itemClick: (Int) -> Unitto your adapter.

将函数传递val itemClick: (Int) -> Unit给您的适配器。

class MyRecyclerViewAdapter(params , val itemClick: (Int) -> Unit): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
internal inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    ...
    itemView.setOnClickListener( {itemClick(layoutPosition)} )
  } 
}  

In your fragment use the returned value position

在您的片段中使用返回的值 position

val myAdapter = MyRecyclerViewAdapter(params) { position ->
    // do something
}

回答by itayrabin

Either creating a listener interface in the adapter or using regular old getters, if I understand your question correctly.

如果我正确理解您的问题,可以在适配器中创建侦听器接口或使用常规的旧 getter。

回答by Code-Apprentice

You have the right idea with using a Bundle. You just need to pass it to the Fragmentby calling setArguments(). Then you retrieve the Bundlein your Fragmentwith getArguments().

使用Bundle. 您只需要Fragment通过调用将其传递给setArguments()。然后你Bundle在你的Fragmentwith 中检索getArguments()

Note that instead of mList.get(position).name, you can do current.name. Similarly for job.

请注意mList.get(position).name,您可以使用代替current.name。对于job.

Another part of the problem is that you create FragmentB on two different places. In one place you also call setArguments() but do not show the fragment. In the other you show the fragment but do not call setArguments(). If you really need to do this from multiple parts of your code you should write a method to avoid these inconsistencies.

问题的另一部分是您在两个不同的地方创建 FragmentB。在一处,您还调用了 setArguments() 但不显示片段。在另一个中,您显示片段但不调用 setArguments()。如果您确实需要从代码的多个部分执行此操作,您应该编写一种方法来避免这些不一致。

回答by ucsunil

You need to pass the Bundle to the fragment through the setArguments(Bundle args) method. Since you have not set arguments, the bundle you try to extract in your Fragment resolves to null.

您需要通过 setArguments(Bundle args) 方法将 Bundle 传递给片段。由于您尚未设置参数,因此您尝试在 Fragment 中提取的包解析为 null。