Android: Displaying Data of AsyncTask in RecyclerView - java

me again :/ I try to setup a AsyncTask.
This is my code, my fragment activity in which i setup the AsyncTask:
public class HomeFragment extends Fragment {
// RecyclerView
RecyclerView recyclerView;
RecyclerView.Adapter rvAdapter;
RecyclerView.LayoutManager rvLayoutManger;
List<NewsData> news_list;
#Nullable
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_home, null);
// RecyclerView Setup
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view1);
rvLayoutManger = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(rvLayoutManger);
rvAdapter = new HomeRecyclerAdapter(getActivity(), news_list);
recyclerView.setAdapter(rvAdapter);
news_list = new ArrayList<>();
load_data_from_server(0);
return view;
}
private void load_data_from_server(int id) {
AsyncTask<Integer, Void, Void> task = new AsyncTask<Integer, Void, Void>() {
#Override
protected Void doInBackground(Integer... integers) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://here is my url ").build();
try {
Response response = client.newCall(request).execute();
JSONArray array = new JSONArray(response.body().toString());
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
NewsData data = new NewsData(object.getInt("id"), object.getString("title"), object.getString("describtion"));
news_list.add(data);
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
System.out.print("End of content");
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
rvAdapter.notifyDataSetChanged();
}
};
task.execute(id);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
I wanna display the title in my RecyclerView so in the RecyclerAdapter:
public class HomeRecyclerAdapter extends RecyclerView.Adapter<HomeRecyclerAdapter.ViewHolder> {
private Context context;
private List<NewsData> news_list;
public HomeRecyclerAdapter(Context context, List<NewsData> news_list) {
this.context = context;
this.news_list = news_list;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_cardviewhome, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.title.setText(news_list.get(position).getTitle());
}
#Override
public int getItemCount() {
return news_list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView title;
public ViewHolder(View itemView){
super(itemView);
title = (TextView) itemView.findViewById(R.id.title_cView);
}
}
To transfer my data i use Getters and Setters:
public class NewsData {
private int id;
private String title, describtion;
public NewsData(int id, String title, String describtion){
this.id = id;
this.title = title;
this.describtion = describtion;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle(){
return title;
}
public void setTitle(String title){
this.title = title;
}
public String getDescribtion(){
return describtion;
}
public void setDescribtion(String describtion) {
this.describtion = describtion;
}
But now i got the Problem that when i run it, it crash. It crashed because of
NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at com.example.andreundjulia.test.Adapters.HomeRecyclerAdapter.getItemCount(HomeRecyclerAdapter.java:53)
Anyone maybe know what to do or what is wrong here ? I realy cant continue :/ I hope you guys can understand my english its not realy good but well I already wanna thank you because you clicked on this thread and try to help :-)

You're setting your data into the adapter with a null list: rvAdapter = new HomeRecyclerAdapter(getActivity(), news_list);. Then below you initialize news_list = new ArrayList<>(). Move the initialization before the adapter creation.

You're never inicialize you news_list and so, when you call rvAdapter = new HomeRecyclerAdapter(getActivity(), news_list); you're put a null reference.
You need do the initialization before:
List<NewsData> news_list = new ArrayList<>();

In oncreateview of your fragment you need to initialize arraylist before setting adapter

Related

Attempt to invoke virtual method 'void.estate.view.adapter.plucking.EmployeePluckingSessionAdapter.setList(java.util.List)' on a null object reference

I am getting this error but I cannot find the reason.
This is my code of Adapter.
public class EmployeePluckingSessionAdapter extends RecyclerView.Adapter<EmployeePluckingSessionAdapter.EmployeePluckingSessionAdapterHolder> {
private SubSessionListActivity.AdapterEvents adapterEvents;
private List<EmployeePluckingCollectionSummary> employeePluckingCollectionSummaries = new ArrayList<>();
public EmployeePluckingSessionAdapter(SubSessionListActivity.AdapterEvents adapterEvents){
this.adapterEvents = adapterEvents;
}
public void setList(List<EmployeePluckingCollectionSummary> employeePluckingCollectionSummaries){
this.employeePluckingCollectionSummaries = employeePluckingCollectionSummaries;
}
public void setAdapterEvents(SubSessionListActivity.AdapterEvents adapterEvents) {
this.adapterEvents = adapterEvents;
}
#NonNull
#Override
public EmployeePluckingSessionAdapterHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.plucking_summary_data, parent, false);
return new EmployeePluckingSessionAdapterHolder(view);
}
#Override
public void onBindViewHolder(#NonNull EmployeePluckingSessionAdapterHolder holder, int position) {
EmployeePluckingCollectionSummary employeePluckingCollectionSummary = employeePluckingCollectionSummaries.get(position);
holder.userName.setText(String.valueOf(employeePluckingCollectionSummary.getEmployeeName()));
holder.userId.setText(String.valueOf(employeePluckingCollectionSummary.getEmployeeId()));
holder.session.setText(String.valueOf(employeePluckingCollectionSummary.getSessionName()));
holder.sessionTotal.setText(String.valueOf(employeePluckingCollectionSummary.getWeight()));
}
#Override
public int getItemCount() {
return 0;
}
class EmployeePluckingSessionAdapterHolder extends RecyclerView.ViewHolder {
private final LinearLayout plucking_data;
private final TextView userName;
private final TextView userId;
private final TextView session;
private final TextView sessionTotal;
public EmployeePluckingSessionAdapterHolder(View view) {
super(view);
this.plucking_data = view.findViewById(R.id.plucking_data);
this.userName = view.findViewById(R.id.userName);
this.userId =view.findViewById(R.id.userId);
this.session = view.findViewById(R.id.session);
this.sessionTotal = view.findViewById(R.id.sessionTotal);
}
}
}
This is my code of Activity.
public class PluckingChecklistReportActivity extends AppCompatActivity {
private PluckingCollectionViewModel pluckingCollectionViewModel;
RecyclerView recyclerView;
List<EmployeePluckingCollectionSummary> pluckingSummary = new ArrayList<>();
LinearLayoutManager linearLayoutManager;
EmployeePluckingSessionAdapter employeePluckingSessionAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_plucking_checklist_report);
pluckingCollectionViewModel = new ViewModelProvider(this).get(PluckingCollectionViewModel.class);
recyclerView = findViewById(R.id.plucking_data);
linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setAdapter(employeePluckingSessionAdapter);
recyclerView.setLayoutManager(linearLayoutManager);
pluckingCollectionViewModel.getEmployeePluckingSessionSummary().observe(this, new Observer<List<EmployeePluckingCollectionSummary>>() {
#Override
public void onChanged(List<EmployeePluckingCollectionSummary> employeePluckingCollectionSummaries) {
pluckingSummary = employeePluckingCollectionSummaries;
employeePluckingSessionAdapter.setList(pluckingSummary);
}
});
}
}
I found that "pluckingSummary" list is null. I don't know how to set values to the list. I tried to set the values to arrayList after convert it into JSONObject but it did not work as well. I get values correctly when I use System.out.println(new Gson().toJson(employeePluckingCollectionSummaries));

recyclerView missing error in Android Studio

I'm a beginner programmer and I'm trying to receive data from the server using node.js and display the list on Android Studio but I keep having the following error:
E/RecyclerView: No adapter attached; skipping layout
D/HistoryActivity: HistoryResponse{result=[com.sooryong.loginexample.data.HistoryData#3303f3c, com.sooryong.loginexample.data.HistoryData#33764c5]}
D/AndroidRuntime: Shutting down VM
As you can see, I can't recall my list properly as well and I don't know how to fix it. Here are my codes:
public interface ServiceApi {
#POST("/user/login")
Call<LoginResponse> userLogin(#Body LoginData data);
#POST("/user/join")
Call<JoinResponse> userJoin(#Body JoinData data);
#GET("/test/history")
Call<HistoryResponse> getData();
}
HistoryData.java
public class HistoryData {
#SerializedName("eventID")
private int eventID;
#SerializedName("eventType")
private String eventType;
#SerializedName("eventDate")
private String eventDate;
#SerializedName("userID")
private int userID;
#SerializedName("sensorID")
private String sensorID;
public HistoryData(int eventID, String eventType, String eventDate, int userID, String sensorID) {
super();
this.eventID = eventID;
this.eventType = eventType;
this.eventDate = eventDate;
this.userID = userID;
this.sensorID = sensorID;
}
public int getEventID() {
return eventID;
}
public String getEventType() {
return eventType;
}
public String getEventDate() { return eventDate; }
public int getUserID() {
return userID;
}
public String getSensorID() { return sensorID; }
}
HistoryResponse.java
public class HistoryResponse {
#SerializedName("code")
public String code;
#SerializedName("message")
public String message;
#SerializedName("result")
public List<HistoryData> result;
#Override
public String toString() {
return "HistoryResponse{" + "result=" + result +'}';
}
}
HistoryActivity.java
public class HistoryActivity extends AppCompatActivity {
HistoryResponse dataList;
List<HistoryData> dataInfo;
private RecyclerView recyclerView;
private RecyclerAdapter recyclerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recycler_view);
dataInfo = new ArrayList<>();
recyclerView = findViewById(R.id.recyclerView);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
ServiceApi apiInterface = RetrofitClient.getClient().create(ServiceApi.class);
Call<HistoryResponse> call = apiInterface.getData();
call.enqueue(new Callback<HistoryResponse>() {
#Override
public void onResponse(Call<HistoryResponse> call, Response<HistoryResponse> response) {
dataList = response.body();
Log.d("Response", dataList.toString());
dataInfo = dataList.result;
recyclerAdapter = new RecyclerAdapter(getApplicationContext(), dataInfo);
recyclerView.setAdapter(recyclerAdapter);
}
#Override
public void onFailure(Call<HistoryResponse> call, Throwable t) {
Log.d("Response", t.getMessage());
}
});
}
}
RecyclerAdapter.java
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder>{
private Context c;
private List<HistoryData> dataList;
public RecyclerAdapter(Context c, List<HistoryData> dataList) {
this.c = c;
this.dataList = dataList;
}
#NonNull
#Override
public RecyclerAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(c).inflate(R.layout.recycler_view, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerAdapter.MyViewHolder holder, int position) {
holder.id.setText(dataList.get(position).getSensorID());
holder.type.setText("" + dataList.get(position).getEventType());
holder.date.setText("" + dataList.get(position).getEventDate());
}
#Override
public int getItemCount() {
return (dataList == null) ? 0 : dataList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView id;
TextView type;
TextView date;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
id = (TextView)itemView.findViewById(R.id.sensorID);
type = (TextView)itemView.findViewById(R.id.eventType);
date = (TextView)itemView.findViewById(R.id.eventDate);
}
}
}
I don't think the data is being initialized properly inside the RecyclerAdapter class. Is it because I couldn't load the data properly from the server?
I ever face the same issue similiar to this.
What I've done was: initialize the adapter once only the activity created:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recycler_view);
dataInfo = new ArrayList<>();
initAdapter();
....
}
private void initAdapter() {
//The adapter should create once in onCreate
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext, LinearLayoutManager.VERTICAL, false);
recyclerAdapter = new RecyclerAdapter(getApplicationContext(), dataInfo);
recyclerView.setAdapter(recyclerAdapter);
}
Then when in callback result: you can clear the previous data before reload to the adapter:
call.enqueue(new Callback<HistoryResponse>() {
#Override
public void onResponse(Call<HistoryResponse> call, Response<HistoryResponse> response) {
dataList = response.body();
dataInfo.clear(); // <- here we clear all previous data before reload result to the adapter.
dataInfo = dataList.result;
recyclerAdapter.notifyDataSetChanged()
#Override
public void onFailure(Call<HistoryResponse> call, Throwable t) {
Log.d("Response", t.getMessage());
}
});
Hope this help.

Cannot call method of RecyclerView adapter from an activity

I am trying to set the data for recycler view to display from an AsyncTask. I am calling the method setdataEntries from the postExecute of inner class AsyncTask. But the android studio is showing me error could not find the method.
Adapter class
public class EntryAdapter extends RecyclerView.Adapter<EntryAdapter.ViewHolder> {
List<UserTuple> entries;
final private itemClickListener mOnClickListener;
public interface itemClickListener{
void onItemClick(UserTuple utuple);
}
public EntryAdapter(itemClickListener clickhandler) {
mOnClickListener = clickhandler;
}
public void setdataEntries(List<UserTuple> Data) {
entries = Data;
notifyDataSetChanged();
}
#Override
public EntryAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.singleusertuple,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(EntryAdapter.ViewHolder holder, int position) {
holder.Username.setText(entries.get(position).getUsername());
holder.Password.setText(entries.get(position).getPassword());
}
#Override
public int getItemCount() {
return entries.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView Username;
private TextView Password;
private CardView card;
public ViewHolder(View itemView) {
super(itemView);
Username = itemView.findViewById(R.id.susername);
Password=itemView.findViewById(R.id.pass);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int adapterPosition = getAdapterPosition();
UserTuple ut=new UserTuple(entries.get(adapterPosition).getUsername(),entries.get(adapterPosition).getPassword());
mOnClickListener.onItemClick(ut);
}
}
}
Calling Activity
public class Usertuple extends AppCompatActivity implements EntryAdapter.itemClickListener {
private RecyclerView recyclerView ;
private RecyclerView.Adapter adapater;
private SnapHelper snapHelper;
private List<UserTuple> entries;
private ProgressBar mLoadingIndicator;
private Bundle extras;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logins);
extras = getIntent().getExtras();
//String site= extras.getString("sitename");
mLoadingIndicator = (ProgressBar) findViewById(R.id.pb_loading_indicator);
Log.i("Logins","Size of returned list "+entries.size());
recyclerView = findViewById(R.id.recycleview);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
adapater = new EntryAdapter(this);
recyclerView.setAdapter(adapater);
snapHelper= new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
dataView();
}
public void dataView() {
String site= extras.getString("sitename");
recyclerView.setVisibility(View.VISIBLE);
new FetchDataTask().execute(site);
}
#Override
public void onItemClick(UserTuple utuple) {
}
private String key(){
SharedPreferences sharedPref = getSharedPreferences(
"User", this.MODE_PRIVATE);
final String passphrase = sharedPref.getString("userid", "none");
return passphrase;
}
public void showerror(){
recyclerView.setVisibility(View.GONE);
Toast.makeText(this,"Error in retrieving",Toast.LENGTH_SHORT).show();
}
public setdata(List<UserTuple> data){
adapater.setdataEntries(data);
}
public class FetchDataTask extends AsyncTask<String, Void, List<UserTuple>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mLoadingIndicator.setVisibility(View.VISIBLE);
}
#Override
protected List<UserTuple> doInBackground(String... params) {
/* If there's no zip code, there's nothing to look up. */
if (params.length == 0) {
return null;
}
String site = params[0];
try {
AppDatabase db = Room.databaseBuilder(getApplicationContext(),AppDatabase.class, "production")
.build();
entries =db.entryDao().getSpecific(site);
for(UserTuple ut : entries){
Log.i("password",ut.getPassword());
String st = new Decryption().decrypt(ut.getPassword(),key());
Log.i("After decryption",st);
ut.setPassword(st);
}
return entries;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(List<UserTuple> Data) {
mLoadingIndicator.setVisibility(View.INVISIBLE);
if (Data != null) {
adapater.setdataEntries(Data);
} else {
showerror();
}
}
}
}
I want the database calls to be a background task. I don't want the activity to freeze waiting for database calls. Any ideas? Thanks
Declare adapter like
private EntryAdapter adapter;
instead of
private RecyclerView.Adapter adapater;
because RecyclerView.Adapter class does not have any method named setdataEntries but only EntryAdapter class has this method so only the object of type EntryAdapter can call setdataEntries method.
Or you can use down-casting as
((EntryAdapter)adapater).setdataEntries(data);

Parse JSON value to an Activity from a ListView. Beginner

I just learned java and also android app development.
I've been able to populate json object to a listview from a web-service to my NewActivity.class. but having problems with setting OnItemClickListener for my listview by parsing json value from my jsonparser class to my DetailActivity.class.
I tried reading some answers from here but got lost at some point. I Will be very glad if anyone makes an input. Thanks
JSON PARSER CLASS
public class JSONParser {
public static List<Events> parseFeed(String content) {
try {
JSONArray ar = new JSONArray(content);
List<Events> eventList = new ArrayList<>();
for (int i = 0; i < ar.length(); i++) {
JSONObject obj = ar.getJSONObject(i);
String headline = obj.optString("Content");
Events events = new Events();
events.setId(obj.getInt("id"));
events.setTitle(obj.getString("Title"));
events.setPostDate(obj.getString("PostDate"));
events.setSummary(obj.getString("Summary"));
events.setContent(obj.getString("Content"));
events.setPicture(obj.getString("Picture"));
eventList.add(events);
}
return eventList;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
This is my NewActivity.class.
public class NewActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
final String LOG = "ListActivity";
private List<Events> eventsList;
private ListView lvEvents;
ProgressBar pb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
lvEvents = (ListView) findViewById(R.id.listview1);
pb = (ProgressBar) findViewById(R.id.progressBar);
pb.setVisibility(View.INVISIBLE);
if (isOnline()){
requestData("http://json/events.php");
} else {
Toast.makeText(this, "No Internet Connection", Toast.LENGTH_LONG).show();
}
}
protected void updateDisplay() {
EventListAdapter adapter = new EventListAdapter(this, R.layout.mylist_view, eventsList );
lvEvents.setAdapter(adapter);
lvEvents.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(NewActivity.this, EventsDetail.class);
intent.putExtra("selectedEvents", eventlist[position]);
startActivity(intent);
}
private void requestData(String uri){
MyTask task = new MyTask();
task.execute(uri);
}
protected boolean isOnline(){
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netinfo = cm.getActiveNetworkInfo();
if (netinfo != null && netinfo.isConnectedOrConnecting()) {
return true;
} else {
return false;
}
}
public class MyTask extends AsyncTask<String, String, List<Events>> {
#Override
protected void onPreExecute() {
pb.setVisibility(View.VISIBLE);
}
#Override
protected List<Events> doInBackground(String... params) {
String data = HttpManager.getData(params[0]);
eventsList = JSONParser.parseFeed(data);
for (Events events : eventsList) {
try {
String imageUrl = events.getPicture();
InputStream imageRead = (InputStream) new URL(imageUrl).getContent();
Bitmap bitmap = BitmapFactory.decodeStream(imageRead);
events.setBitmap(bitmap);
imageRead.close();
} catch (Exception e){
e.printStackTrace();
}
}
return eventsList;
}
#Override
protected void onPostExecute(List<Events> results) {
eventsList = results;
updateDisplay();
pb.setVisibility(View.INVISIBLE);
}
}
And this my Events.class
public class Events implements Serializable {
public int id;
public String Title;
public String PostDate;
public String Summary;
public String Content;
public String Picture;
public Bitmap bitmap;
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPicture() {
return Picture;
}
public void setPicture(String picture) {
Picture = picture;
}
public String getPostDate() {
return PostDate;
}
public void setPostDate(String postDate) {
PostDate = postDate;
}
public String getSummary() {
return Summary;
}
public void setSummary(String summary) {
Summary = summary;
}
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
Lastly my DetailActivity.class which has three TextView to receive the JSON values
public class EventsDetail extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_events_detail);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TextView detailname = (TextView) findViewById(R.id.detailTitle);
TextView eventDetail = (TextView) findViewById(R.id.detailContent);
TextView eventDate = (TextView) findViewById(R.id.detailDate);
}
You need to this way:
1. Make class Serializable
public class Events implements Serializable{
// Other stuff
}
2. onItemClick of ListView.
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(NewActivity.this, EventsDetail.class);
intent.putExtra("object",eventList[position]);
startActivity(intent);
}
3. EventsDetail class.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_events_detail);
// Other stuff
Events event = (Events) getIntent().getSerializableExtra("object");
}
Hope this will help you.
You can try this :)
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(NewActivity.this, EventsDetail.class);
//try type casting Events instance as Serializable :)
Events selectedEvent = eventList[position];
intent.putExtra("selectedEvent",(Serializable)selectedEvent);
startActivity(intent);
}
This will add selected event as an arguement to your intent :) which is responsible for invoking eventdetail activity :)
and in event detail activity :)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_events_detail);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Events passedEvent = getIntent().getSerializableExtra("selectedEvent");
TextView detailname = (TextView) findViewById(R.id.detailTitle);
TextView eventDetail = (TextView) findViewById(R.id.detailContent);
TextView eventDate = (TextView) findViewById(R.id.detailDate);
//set the textview values now from the recieved events instance :)
}
All being said :) for the above code to work you must implement implements Serializable to your Event class :)
This is very simple :) just requires you to specify implement Serializable and write setter and getter for all the properties of Events class :) Thats all :)
Here is a link for how to implement serialization :) http://www.vogella.com/tutorials/JavaSerialization/article.html
Hope my answer helped you :) Happy coding buddy :)

onClickListener on a CardView in a RecyclerView created by a Fragment in a Fragment in an Activity

This is a multi-part question.
First Part:
I'm building an app to track local events. Currently, I have a Fragment containing a RecyclerView consisting of CardViews which each represent one event. What I want is to be able to tap a card and replace the Fragment with a new one showing more details about that card's event.
I've searched Google for several hours, but it none of the solutions presented seemed to work when I tried them. Below is the class for the fragment Tab1 which creates the RecyclerView adapter.
public class Tab1 extends Fragment {
//RecyclerView
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
//ProgressDialog
private ProgressDialog pDialog;
// URL to get contacts JSON
private static String url = "removed";
// JSON Node names
private static final String TAG_EVENT = "event";
private static final String TAG_EVENTNAME = "Event Name";
private static final String TAG_LOCATION = "Location";
private static final String TAG_RAINLOCATION = "Rain Location";
private static final String TAG_ORG = "Org";
private static final String TAG_TIME = "Time";
private static final String TAG_RSVP = "RSVP";
// events JSONArray
JSONArray events = null;
private List<Event> eventlist;
private RecyclerView rv;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_2,container,false);
// Calling async task to get json
new GetEvents().execute();
return v;
}
public void onViewCreated(View view, Bundle savedInstanceState) {
mRecyclerView = (RecyclerView) getView().findViewById(R.id.my_recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
}
private class GetEvents extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null) {
try {
eventlist = new ArrayList<>();
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
events = jsonObj.getJSONArray(TAG_EVENT);
// looping through All Events
for (int i = 0; i < events.length(); i++) {
JSONObject c = events.getJSONObject(i);
String eventName = c.getString(TAG_EVENTNAME);
String location = c.getString(TAG_LOCATION);
String rain = c.getString(TAG_RAINLOCATION);
String org = c.getString(TAG_ORG);
String time = c.getString(TAG_TIME);
SimpleDateFormat format = new SimpleDateFormat("EEE, MMM d, h:mm a", Locale.US);
SimpleDateFormat parserSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
try {
Date date = parserSDF.parse(time);
time = format.format(date);
} catch (ParseException e) {
e.printStackTrace();
}
String rsvp = c.getString(TAG_RSVP);
eventlist.add(new Event(eventName, time.toUpperCase(), location, R.drawable.pace));
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
RVAdapter adapter = new RVAdapter(eventlist);
mRecyclerView.setAdapter(adapter);
}
}
}
And here is the RVAdapter
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.EventViewHolder> {
public static class EventViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cv;
TextView eventName;
TextView eventTime;
TextView eventLocation;
ImageView orgPhoto;
private ClickListener clickListener;
EventViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cv);
eventName = (TextView)itemView.findViewById(R.id.event_name);
eventTime = (TextView)itemView.findViewById(R.id.event_time);
eventLocation = (TextView)itemView.findViewById(R.id.event_location);
orgPhoto = (ImageView)itemView.findViewById(R.id.org_photo);
itemView.setOnClickListener(this);
}
public interface ClickListener {
/**
* Called when the view is clicked.
*
* #param v view that is clicked
* #param position of the clicked item
*/
public void onClick(View v, int position, String title);
}
/* Setter for listener. */
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
#Override
public void onClick(View v) {
clickListener.onClick(v, getPosition(), eventName.getText().toString());
}
}
List<Event> events;
RVAdapter(List<Event> events){
this.events = events;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public EventViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.event_card, viewGroup, false);
EventViewHolder pvh = new EventViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(EventViewHolder EventViewHolder, final int i) {
EventViewHolder.eventName.setText(events.get(i).name);
EventViewHolder.eventTime.setText(events.get(i).time);
EventViewHolder.eventLocation.setText(events.get(i).location);
EventViewHolder.orgPhoto.setImageResource(events.get(i).orgPhoto);
EventViewHolder.setClickListener(new EventViewHolder.ClickListener() {
#Override
public void onClick(View v, int pos, String title) {
//onClick
}
});
}
#Override
public int getItemCount() {
return events.size();
}
}
You can see I've attempted to implement the interface and onClickListener.
Is this the right way? I've tried to test it by making toasts with the name of the Card clicked, but it doesn't appear to have worked, or at least the toast is not showing up.
Second Part:
If this is the correct way and it should be working, where/how do I write the code to replace the fragment with the new one showing more information about the event? Can it go in the Adapter class? The Tab1 fragment is actually inside of another fragment which is inside of an activity. I'd like to replace Tab1's parent fragment.
See if this helps
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.EventViewHolder> {
public static class EventViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cv;
TextView eventName;
TextView eventTime;
TextView eventLocation;
ImageView orgPhoto;
EventViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
eventName = (TextView) itemView.findViewById(R.id.event_name);
eventTime = (TextView) itemView.findViewById(R.id.event_time);
eventLocation = (TextView) itemView.findViewById(R.id.event_location);
orgPhoto = (ImageView) itemView.findViewById(R.id.org_photo);
}
#Override
public void onClick(View view) {
//do stuff
}
}
List<Event> events;
RVAdapter(List<Event> events){
this.events = events;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public EventViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.event_card, viewGroup, false);
return new EventViewHolder(v);
}
#Override
public void onBindViewHolder(EventViewHolder EventViewHolder, final int i) {
EventViewHolder.eventName.setText(events.get(i).name);
EventViewHolder.eventTime.setText(events.get(i).time);
EventViewHolder.eventLocation.setText(events.get(i).location);
EventViewHolder.orgPhoto.setImageResource(events.get(i).orgPhoto);
}
#Override
public int getItemCount() {
return events.size();
}
}
For the 2nd part of your question. Its better for the ParentActivity hosting both Frag1 & Frag2 to switch the fragment. So say in the ParentActivity, there is a framelayout (R.id.container) that is hosting Frag1.
You can pass the event call back to the activity, and you can do this to replace the fragment in the container
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, Frag2)
.commit();

Categories