web-dev-qa-db-ja.com

Recyclerviewからフラグメントにデータを渡す方法

FragmentにrecyclerViewが入力されていて、新しいFragmentを起動してアダプターからデータを渡したいのですが、バンドルを使用しようとしますが、これは常に私のアダプタークラスにnull値を与えます

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

これは私がローンチしたい私の新しいフラグメントです

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

}

}

これは、フラグメントとrecyclerviewアダプターをインターフェイスに接続する方法です

public interface FragmentCommunication {
void respond(int position);

}

これは、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) {
        FragmentB fragmentB=new FragmentB();
        FragmentManager manager=getFragmentManager();
        FragmentTransaction transaction=manager.beginTransaction();
        transaction.replace(R.id.dumper,fragmentB).commit();
    }

};

}

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

}

したがって、fragmentBを起動し、recyclerviewアダプタからfragmentBにデータを渡す正しい方法は何ですか

6
Ahmed Ezzat

回答をありがとう、私は文字列値を持つインターフェースを使用してアダプターをrecyclerviewを含むフラグメントに接続する問題を解決しました、そしてここで他のフラグメントは私が正確に行ったことです:これはインターフェースです

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

これはアダプターです

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

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;

    }


}
9
Ahmed Ezzat

Kotlinを使用している場合、解決策ははるかに簡単です。 元の回答はこちら

関数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)} )
  } 
}  

フラグメントで、戻り値positionを使用します

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

質問を正しく理解できれば、アダプターでリスナーインターフェイスを作成するか、通常の古いゲッターを使用します。

1
itayrabin

あなたはBundleを使うことで正しい考えを持っています。 setArguments() を呼び出して、Fragmentに渡す必要があります。次に、_ getArguments() を使用してBundleFragmentを取得します。

mList.get(position).nameの代わりに、current.namejobも同様です。

問題の別の部分は、2つの異なる場所にFragmentBを作成することです。 1つの場所でsetArguments()も呼び出しますが、フラグメントは表示しません。もう一方ではフラグメントを表示しますが、setArguments()を呼び出さないでください。コードの複数の部分からこれを行う必要がある場合は、これらの不整合を回避するメソッドを作成する必要があります。

0
Code-Apprentice

バンドルをsetArguments(Bundle args)メソッドを介してフラグメントに渡す必要があります。引数を設定していないため、フラグメントで抽出しようとするバンドルはnullに解決されます。

0
ucsunil