我正在使用Json来获取应用程序的数据和图像。图像显示在连接到MainActivity的片段(Tab1.java)内的RecyclerView中。我想以这种方式进行设置,以便当用户单击RecyclerView中的图像时,将启动一个新的Activity(ViewImage.java),并在其中显示该图像。
到目前为止,我已经能够获取Json数据并将其显示在回收者视图中。图像显示完美,但是当我尝试设置“ setItemOnClickListener”时,应用程序开始崩溃(我在 Tab1.java 中用注释标记了该行)。
Tab1.java
/*
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link Tab1.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link Tab1#newInstance} factory method to
* create an instance of this fragment.
*/
public class Tab1 extends Fragment implements CardAdapter.OnItemClickListener{
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public static final String EXTRA_URL = "imageUrl";
private RecyclerView mRecyclerView;
private CardAdapter mCardAdapter;
private ArrayList<Card> mCardList;
TextView textView;
private OnFragmentInteractionListener mListener;
public Tab1() {
// Required empty public constructor
}
/*
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment Tab1.
*/
// TODO: Rename and change types and number of parameters
public static Tab1 newInstance(String param1, String param2) {
Tab1 fragment = new Tab1();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
// @Override
public void onCreate(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_tab1, container, false);
mRecyclerView = v.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mCardList = new ArrayList<>();
/*
* Retrofit code to fetch the Json data
*/
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService service = retrofit.create(ApiService.class);
Call<JsonResponse> call = service.getPopulationData();
final StringBuffer flagData = new StringBuffer();
call.enqueue(new Callback<JsonResponse>(){
@Override
public void onResponse(Call<JsonResponse> call, Response<JsonResponse> response) {
ArrayList<Worldpopulation> population=new ArrayList(response.body()
.getWorldpopulation());
for (Worldpopulation j : population) {
String countryName = j.getCountry();
String imageUrl = j.getFlag();
int rank = j.getRank();
mCardList.add(new Card(imageUrl, countryName, rank));
}
mCardAdapter = new CardAdapter(getActivity(), mCardList);
mRecyclerView.setAdapter(mCardAdapter);
// This particular line of code is causing the application to crash.
// And I cannot figure out how this is supposed to be implemented.
mCardAdapter.setItemOnClickListener((CardAdapter.OnItemClickListener) getContext());
}
@Override
public void onFailure(Call<JsonResponse> call, Throwable t) {
Log.d("JSONError", t.getMessage());
}
});
// Inflate the layout for this fragment
return v;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
@Override
public void onItemClick(int position) {
Intent imagePreview = new Intent(getActivity(), ViewImage.class);
Card clickedItem = mCardList.get(position);
imagePreview.putExtra(EXTRA_URL, clickedItem.getImageUrl());
startActivity(imagePreview);
}
/*
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
CardAdapter.java
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.CardViewHolder> {
private Context mContext;
private ArrayList<Card> mCardList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setItemOnClickListener(OnItemClickListener listener) {
mListener = listener;
}
public CardAdapter(Context context, ArrayList<Card> cardList) {
mContext = context;
mCardList = cardList;
}
@Override
public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.card, parent, false);
return new CardViewHolder(v);
}
@Override
public void onBindViewHolder(CardViewHolder holder, int position) {
Card currentItem = mCardList.get(position);
String imageUrl = currentItem.getImageUrl();
String countryName = currentItem.getCountryName();
int rank = currentItem.getRank();
holder.mTextViewCountry.setText(countryName);
holder.mTextViewRank.setText("Rank: " + rank);
Picasso.get().load(imageUrl).fit().centerInside().into(holder.mImageView);
}
@Override
public int getItemCount() {
return mCardList.size();
}
public class CardViewHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public TextView mTextViewCountry;
public TextView mTextViewRank;
public CardViewHolder(View itemView) {
super(itemView);
mImageView = itemView.findViewById(R.id.image_view);
mTextViewCountry = itemView.findViewById(R.id.text_view_country_name);
mTextViewRank = itemView.findViewById(R.id.text_view_rank);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mListener.onItemClick(position);
}
}
}
});
}
}
}
ViewImage.java
public class viewimage extends appcompatactivity {
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_view_image);
// imageview where the image is to be displayed in this activity
imageview imageview = findviewbyid(r.id.fullscreenimage);
bundle bundle = getintent().getextras();
if (bundle != null) {
string imageurl = bundle.getstring("extra_url");
if (imageurl != null) {
picasso.get().load(imageurl).fit().centerinside().into(imageview);
}
}
}
}
答案 0 :(得分:3)
您已经知道RecyclerView
类中不再提供此方法。
我在onClick
中实现RecyclerView
事件的方法是这样的:
class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
interface OnClickListener {
void onClick(Item item);
}
private final List<Item> dataset;
private final OnClickListener l;
public MyAdapter(List<Item> data, OnClickListener listener) {
this.dataset = data;
this.l = listener;
}
@Override MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = //inflate layout
MyClick click = new MyClick() {
onClick(int position) {
if (l != null) {
l.onClick(dataset.get(position));
}
}
};
return new MyViewHolder(click, v);
}
static class MyViewHolder {
final MyClick l;
public MyViewHolder(MyClick listener, View view) {
super(view);
l = listener;
// inflate views
view.setOnClickListener(new OnClickListener() {
if (l != null) {
l.onClick(getAdapterPosition());
}
});
}
interface MyClick {
void onClick(int position);
}
}
}
class MyActivity extends AppCompatActivity {
@Override void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set layout
MyAdapter adapter = new MyAdapter(getData(), new OnClickListener() {
@Override onClick(Item item) {
// do stuff with item
}
});
}
}