【问题标题】:Android recycleview pass parameters to another fragment in the same activityAndroid recyclerview 将参数传递给同一活动中的另一个片段
【发布时间】:2020-12-03 05:07:44
【问题描述】:

我已经实现了 recyclerview 并且工作正常,但是当我想通过 Bundle 将 recyclerview 的单击行上的参数传递给同一活动中的另一个片段时 此行有语法错误:

 getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragmentsContainer, f ).commit();

getActivity 显示语法错误

//适配器的完整代码:

package com.example.miniprojetandroid.adapters;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.miniprojetandroid.R;
import com.example.miniprojetandroid.models.Bike;
import com.example.miniprojetandroid.ui.fragments.DetailsFragment;


public class BikesAdapter  extends RecyclerView.Adapter<BikesAdapter.BikesViewHolder> {

    private final ArrayList<Bike> bikes;
    private Context mContext;
    private Callback mCallback;

public BikesAdapter(Context mContext, ArrayList<Bike> bikes) {
        this.mContext = mContext ;
        this.bikes = bikes;
        }

@NonNull
@Override
public BikesAdapter.BikesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View mItemView = LayoutInflater.from(mContext).inflate(R.layout.bike_list_item, parent, false);
        return new BikesViewHolder(mItemView, this);
        }

@Override
public void onBindViewHolder(@NonNull BikesAdapter.BikesViewHolder holder, int position) {
final Bike singleItem = bikes.get(position);

        holder.BikeName.setText(singleItem.getModel());
        holder.BikeImage.setBackgroundResource(singleItem.getImage());
        holder.bikeView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCallback.onItemClicked(singleItem);
            }
        });
        holder.BikeImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
        Toast.makeText(mContext,singleItem.getModel(),Toast.LENGTH_SHORT).show();
        }
        });
        }

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

public class BikesViewHolder extends RecyclerView.ViewHolder {

    public final TextView BikeName;
    public final ImageView BikeImage;
    public final Button bikeView;
    final BikesAdapter mAdapter;

    public BikesViewHolder(@NonNull View itemView, BikesAdapter mAdapter) {
        super(itemView);
        this.BikeName = itemView.findViewById(R.id.bikeName);
        this.BikeImage = itemView.findViewById(R.id.bikeImage);
        this.bikeView = itemView.findViewById(R.id.btn_view);
        this.mAdapter = mAdapter;
    }
}

    public void setCallback(Callback callback) {
        mCallback = callback;
    }

    public interface Callback {
        void onItemClicked(Bike bike);
    }

}

//我的目标片段

package com.example.miniprojetandroid.ui.fragments;

import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.example.miniprojetandroid.R;
import com.example.miniprojetandroid.models.Bike;


public class DetailsFragment extends Fragment {

    Button btnRent, btnFav;
    TextView bike_id,model,type,price;

    public DetailsFragment() {
        // Required empty public constructor
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {

        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.fragment_details, container, false);
        btnRent = v.findViewById(R.id.btnRent);
        btnFav = v.findViewById(R.id.btnFav);
        bike_id = v.findViewById(R.id.bike_id);
        model = v.findViewById(R.id.model);
        type = v.findViewById(R.id.type);
        price = v.findViewById(R.id.price);

        int id = getArguments().getInt("id");
        String model = getArguments().getString("model");
        String type = getArguments().getString("type");
        String price = getArguments().getString("price");
        int image = getArguments().getInt("image");
        Bike bike = new Bike(id,model,type,price,image);
        Log.e("ddddddddd",bike.toString());

        return v;
    }


}

在DetailsFragment中编辑什么来获取选中项的数据?

//我的回收站查看Fragment

    package com.example.miniprojetandroid.ui.fragments;

import android.os.Bundle;
import androidx.fragment.app.Fragment;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.miniprojetandroid.R;

import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.miniprojetandroid.Retrofit.BikeService;
import com.example.miniprojetandroid.Retrofit.RetrofitClient;
import com.example.miniprojetandroid.Retrofit.UserService;
import com.example.miniprojetandroid.adapters.BikesAdapter;
import com.example.miniprojetandroid.models.Bike;
import com.example.miniprojetandroid.models.User;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class FragmentOne extends Fragment implements BikesAdapter.Callback{

    private BikeService apiService;

    private RecyclerView recyclerView;
    private List<Bike> bikes = new ArrayList<Bike>();
    private  BikesAdapter mAdapter;
    List<Bike> result = new ArrayList<Bike>();



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

        View rootView = inflater.inflate(R.layout.fragment_one, container,false);

        recyclerView = rootView.findViewById(R.id.recycler_bikes);

        recyclerView.setHasFixedSize(true);
        recyclerView.setNestedScrollingEnabled(true);

        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(),
                LinearLayoutManager.VERTICAL, false));

        apiService = RetrofitClient.getClient().create(BikeService.class);
        fillData();
        mAdapter = new BikesAdapter(getActivity(), (ArrayList<Bike>) bikes);
        recyclerView.setAdapter(mAdapter);
        mAdapter.setCallback(this);



        return rootView;
    }


    public void fillData(){


        Call<List<Bike>> call = apiService.getBikes();
        call.enqueue(new Callback<List<Bike>>() {
            @Override
            public void onResponse(Call<List<Bike>> call, Response<List<Bike>> response) {
                if(response.isSuccessful()){
                    bikes.addAll(response.body());
                    for(Bike bike: bikes){
                        bike.setImage(R.drawable.ruebike);
                    }
                    Log.e("Bike LIST", bikes.toString());


                    //listView.setAdapter(new UserAdapter(MainActivity.this, R.layout.list_user, list));
                }
            }
            @Override
            public void onFailure(Call<List<Bike>> call, Throwable t) {
                Log.e("ERROR: ", t.getMessage());
            }
        });


        /*bikes.add(new Bike(1,"ECO", "RTT" , "44", R.drawable.ruebike ));
        bikes.add(new Bike(2,"AAA", "RTT" , "33",  R.drawable.ruebike ));
        bikes.add(new Bike(3,"BBB", "RUE" , "11",  R.drawable.ruebike ));
        bikes.add(new Bike(4,"EEE", "SPORT" , "25",  R.drawable.ruebike ));
        bikes.add(new Bike(5,"CCC", "SPORT" , "77", R.drawable.ruebike ));
        Log.e("USERS LIST", bikes.toString());*/
    }



    @Override
    public void onItemClicked(Bike bike) {
        // your codes implementation goes here
        Bundle bundle = new Bundle();
        bundle.putInt("bike_id",bike.getId());
        bundle.putString("model", bike.getModel());
        bundle.putString("type", bike.getType());
        bundle.putString("price", bike.getPrice());
        bundle.putInt("image", bike.getImage());
        DetailsFragment f = new DetailsFragment();
        f.setArguments(bundle);


        getActivity().getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.fragmentsContainer, f )
                .commit();
    }




}

在所有的 sugests 之后我像这样编辑了所有内容,但现在 recyclerview 变空了,很明显,使用 Log.e 方法 fillData() 方法显示数据较晚,而 recyclerview 没有足够早地捕获它

【问题讨论】:

    标签: android android-fragments android-recyclerview


    【解决方案1】:

    (选项 1)您可以在像这样实例化时在适配器中传递您的活动:

    public BikesAdapter(Activity mActivity, Context mContext, ArrayList<Bike> bikes) {
            this.mActivity = mActivity ;
            this.mContext = mContext ;
            this.bikes = bikes;
            }
    

    你甚至可以这样做(你可以从你的活动中获取你的上下文):

    public BikesAdapter(Activity mActivity, ArrayList<Bike> bikes) {
            this.mActivity = mActivity ;
            this.mContext = mActivity ;
            this.bikes = bikes;
            }
    

    (选项 2)或简单地为您的适配器内的 onClickListeners 编写接口回调,并在活动内调用它们以实现适配器。效果更好,更完美。下面是一个示例:

    public class BikesAdapter  extends RecyclerView.Adapter<BikesAdapter.BikesViewHolder> {
        private Callback mCallback;
        private final ArrayList<Bike> bikes;
        private Context mContext;
        public BikesAdapter(Context mContext, ArrayList<Bike> bikes) {
            this.mContext = mContext ;
            this.bikes = bikes;
        }
    
        @Override
        public void onBindViewHolder(@NonNull BikesAdapter.BikesViewHolder holder, int position) {
        final Bike singleItem = bikes.get(position);
        holder.bikeView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {   
             mCallback.onItemClicked(singleItem));
        });
        ...
    
        public void setCallback(Callback callback) {
            mCallback = callback;
        }
    
        public interface Callback {
            void onItemClicked(Bike bike);
        }
    }
    

    在您实现适配器的活动(片段)中,您实现接口并设置回调,就像这样并覆盖方法:

    public class FragmentOne extends Fragment implements BikesAdapter.Callback {
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
            View rootView = inflater.inflate(R.layout.fragment_one, container,false);
            mAdapter = new BikesAdapter(getActivity(), (ArrayList<Bike>) bikes);
            mAdapter.setCallback(this);
        }
    
        @Override
        public void onItemClicked(Bike bike) {
            // your codes implementation goes here
        getActivity().getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.fragmentsContainer, f )
            .commit();
        }
    
    }
    

    -------------------以下更新-------------- ------------------

    对您的片段进行这些更改。 更新:

    • 在适配器定义下采用fillData();方法并
    • 在 API 响应中添加 adapter.notifyDataSetChanged();,以便您的适配器收到从 API 获取的新项目中的数据更改的通知。
    
    @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
            View rootView = inflater.inflate(R.layout.fragment_one, container,false);
    
            recyclerView = rootView.findViewById(R.id.recycler_bikes);
    
            recyclerView.setHasFixedSize(true);
            recyclerView.setNestedScrollingEnabled(true);
    
            recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(),
                    LinearLayoutManager.VERTICAL, false));
    
            apiService = RetrofitClient.getClient().create(BikeService.class);
            
            mAdapter = new BikesAdapter(getActivity(), (ArrayList<Bike>) bikes);
            recyclerView.setAdapter(mAdapter);
            mAdapter.setCallback(this);
            fillData();
    
    
            return rootView;
        }
    

    (选项 1)在 API 响应中添加 adapter.notifyDataSetChanged();

    public void fillData(){
    
    
            Call<List<Bike>> call = apiService.getBikes();
            call.enqueue(new Callback<List<Bike>>() {
                @Override
                public void onResponse(Call<List<Bike>> call, Response<List<Bike>> response) {
                    if(response.isSuccessful()){
                        bikes.addAll(response.body());
                        for(Bike bike: bikes){
                            bike.setImage(R.drawable.ruebike);
                        }
                        Log.e("Bike LIST", bikes.toString());
    
                        adapter.notifyDataSetChanged();
                       
                    }
                }
                @Override
                public void onFailure(Call<List<Bike>> call, Throwable t) {
                    Log.e("ERROR: ", t.getMessage());
                }
            });
        }
    

    (选项 2)在适配器中定义一个方法

    package com.example.miniprojetandroid.adapters;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;
    import java.util.ArrayList;
    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;
    import com.example.miniprojetandroid.R;
    import com.example.miniprojetandroid.models.Bike;
    import com.example.miniprojetandroid.ui.fragments.DetailsFragment;
    
    
    public class BikesAdapter  extends RecyclerView.Adapter<BikesAdapter.BikesViewHolder> {
        
       .......
    
       public void addItems(ArrayList<Bike> bikeList) {
            this.bikes = bikeList;
            notifyDataSetChanged();        
        }
    
         
    }
    

    然后只需在您的 API 响应中调用此方法,而不是像这样调用 notifyDataSetChanged();

    public void fillData(){
    
    
            Call<List<Bike>> call = apiService.getBikes();
            call.enqueue(new Callback<List<Bike>>() {
                @Override
                public void onResponse(Call<List<Bike>> call, Response<List<Bike>> response) {
                    if(response.isSuccessful()){
                        bikes.addAll(response.body());
                        for(Bike bike: bikes){
                            bike.setImage(R.drawable.ruebike);
                        }
                        Log.e("Bike LIST", bikes.toString());
    
                        adapter.addItems(bikes);
                       
                    }
                }
                @Override
                public void onFailure(Call<List<Bike>> call, Throwable t) {
                    Log.e("ERROR: ", t.getMessage());
                }
            });
        }
    

    无论哪种方式,您都可以通过 API 通知适配器新项目。并且您可以再次显示您的列表。

    问题

    在DetailsFragment中编辑什么来获取选中项的数据?

    有两种方法。

    (选项1)根据您的实现,只需在DetailsFragmentonCreate 内的新片段中提取参数,如下所示。

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if (getArguments() != null) {
                Bundle args = getArguments();
                args.getInt("bike_id", null);
                args.getString("model", null);
                args.getString("type", null);
                args.getString("price", null);
                args.getInt("image", null);
            }
        }
    
    

    (选项 2)或简单地定义一个静态方法,通过简单地传递数据来实例化您的片段,如下所示。简单定义here

    private static Bike bike;
    
    public static DetailsFragment newInstance(Bike bikeArg) {
        bike = bikeArg;
        return new DetailsFragment();
    }
    

    添加片段实例时,您可以这样操作

    
    @Override
        public void onItemClicked(Bike bike) {
            getActivity().getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.fragmentsContainer, 
                      DetailsFragment.newInstance(Bike bike))
                    .commit();
        }
    
    

    然后您可以从新的DetailFragment 上的bike 变量中获取所有数据。希望一切顺利。

    【讨论】:

    • 我遵循了您的第二个解决方案,但现在 recyclerview 变为空,并且似乎 filldata 方法显示数据较晚,我将再次编辑代码以显示我所做的更改
    • 你做得很好。但是请看一下我对答案所做的更新。然后一切都会顺利进行。 @FaresBenSlama
    【解决方案2】:

    您不能在回收器视图适配器中使用 getSupportFragmentManager。

    像这样编辑您的适配器类和容器活动

    适配器类

    public class BikesAdapter extends RecyclerView.Adapter<BikesAdapter.BikesViewHolder> {
    private final ArrayList<Bike> bikes;
    private Context mContext;
    private OnItemClickListener listener;
    
    public BikesAdapter(ArrayList<Bike> bikes, Context mContext, OnItemClickListener listener) {
        this.bikes = bikes;
        this.mContext = mContext;
        this.listener = listener;
    }
    
    @NonNull
    @Override
    public BikesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View mItemView = LayoutInflater.from(mContext).inflate(R.layout.bike_list_item, parent, false);
        return new BikesViewHolder(mItemView);
    }
    
    
    @Override
    public void onBindViewHolder(@NonNull BikesViewHolder holder, int position) {
        final Bike singleItem = bikes.get(position);
    
        holder.BikeName.setText(singleItem.getModel());
        holder.BikeImage.setBackgroundResource(singleItem.getImage());
    }
    
    @Override
    public int getItemCount() {
        return bikes.size();;
    }
    
    
    public class BikesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        TextView BikeName;
        ImageView BikeImage;
        Button bikeView;
        WeakReference<OnItemClickListener> listenerReference;
    
        public BikesViewHolder(@NonNull View itemView) {
            super(itemView);
            BikeName = itemView.findViewById(R.id.bikeName);
            BikeImage = itemView.findViewById(R.id.bikeImage);
            bikeView = itemView.findViewById(R.id.btn_view);
    
            listenerReference = new WeakReference<>(listener);
    
            bikeView.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            if (v == bikeView){
                listenerReference.get().onClick(bikes.get(getAdapterPosition()));
            }
        }
    }
    
    public interface OnItemClickListener {
        void onClick(Bike bike);
    }
    

    }

    然后你应该在你的容器活动中调用这个适配器,如下所示

    BikesAdapter adapter = new BikesAdapter(bikeArrayList, this, new BikesAdapter.OnItemClickListener() {
            @Override
            public void onClick(Bike bike) {
                Bundle bundle = new Bundle();
                bundle.putInt("bikeId", bike.getId());
                /*
                .
                .
                .
                Do your stuff here with getSupportFragmentManager()
                 */
            }
        });
    

    然后将此适配器对象设置为您的回收站视图

    【讨论】:

    • 调用新的自行车适配器失败,语法错误,我将编辑问题以显示目标片段
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    • 1970-01-01
    • 2015-12-18
    • 1970-01-01
    • 2018-04-23
    相关资源
    最近更新 更多