Passing an arraylist of arraylists - java

I know it's a commonly asked question and I looked at the solutions online, but I am having a difficulty implementing this on my own.
I have a class which contains three variables: Location, Date and Uri.
I have an Arraylist which consists of multiple Arraylists that contains said class.
For instance:
ArrayList<ArrayList<class>>
I am trying to pass this onto another activity, yet unsuccessful.
I tried both Parcelable and Serializable but none worked.
Edit: Source code added.
Class documentation:
public class imageHolder implements Parcelable
{
private Uri uri;
private Date date;
private Location loc;
public imageHolder(Uri uriAdd, Date dateAdded,Location imgLoc)
{
this.uri = uriAdd;
this.date = dateAdded;
this.loc = imgLoc;
}
public static final Creator<imageHolder> CREATOR = new Creator<imageHolder>() {
#Override
public imageHolder createFromParcel(Parcel in) {
return new imageHolder(in);
}
#Override
public imageHolder[] newArray(int size) {
return new imageHolder[size];
}
};
public Uri getURI() { return this.uri; }
public Date getDate() {return this.date; }
public Location getLocation() {return this.loc; };
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeSerializable(date);
parcel.writeParcelable(uri,i);
parcel.writeParcelable(loc, i);
}
protected imageHolder(Parcel in) {
date = (java.util.Date) in.readSerializable();
uri = in.readParcelable(Uri.class.getClassLoader());
loc = in.readParcelable(Location.class.getClassLoader());
}
}
First activity:
ArrayList<ArrayList<imageHolder>> sepImages = new ArrayList<ArrayList<imageHolder>>();
sepImages = groupPics(images);
Intent nextActivity = new Intent(loadImages.this, storiesScreen.class);
nextActivity.putExtra("images",images);
startActivity(nextActivity);
finishActivity(0);
Second activity:
ArrayList<ArrayList<imageHolder>> sepImages =
(ArrayList<ArrayList<imageHolder>>) getIntent().getParcelableExtra("images");
Log.d("stories","test");

I think the best thing to do here would be to create a new class that implements Parcelable and pass instances of this new class between activities.
public class ParcelableListOfLists implements Parcelable {
private ArrayList<ArrayList<imageHolder>> listOfLists;
public ParcelableListOfLists(ArrayList<ArrayList<imageHolder>> listOfLists) {
this.listOfLists = listOfLists;
}
public ArrayList<ArrayList<imageHolder>> getListOfLists() {
return listOfLists;
}
// parcelable implementation here
}
Once you have this class, you can be in full control of how your data is parceled, and that lets you do some things that you won't be able to do with the Android built-in offerings.
Here's one way you could parcel a list of lists:
#Override
public void writeToParcel(Parcel dest, int flags) {
if (listOfLists != null) {
dest.writeInt(listOfLists.size());
for (ArrayList<imageHolder> list : listOfLists) {
dest.writeTypedList(list);
}
} else {
dest.writeInt(-1);
}
}
And on the other side, you can recreate the list of lists like this:
public ParcelableListOfLists(Parcel in) {
int size = in.readInt();
if (size != -1) {
this.listOfLists = new ArrayList<>(size);
for (int i = 0; i < size; ++i) {
ArrayList<imageHolder> list = in.createTypedArrayList(imageHolder.CREATOR);
listOfLists.add(list);
}
} else {
this.listOfLists = null;
}
}
With all of this together, you can pass your list of lists between activities like this:
Intent nextActivity = new Intent(loadImages.this, storiesScreen.class);
nextActivity.putExtra("images", new ParcelableListOfLists(images));
startActivity(nextActivity);
and retrieve them in the next activity like this:
ParcelableListOfLists plol = getIntent().getParcelableExtra("images");
ArrayList<ArrayList<imageHolder>> images = plol.getListOfLists();

I think that you can use Gson too.
In your build.gradle
implementation 'com.google.code.gson:gson:2.8.4'
In the first activity
Gson gson = new Gson();
String json = gson.toJson(yourObject);
intent.putExtra("yourKey", json);
In the second activity
Gson gson = new Gson();
YourObject yourObject = gson.fromJson(getIntent().getStringExtra("yourKey"), YourObject.class);
Easy and fast.

Ok.
Your Model
public class ImageHolder implements Serializable {
// Use String here, to avoid serialization problems
private String uri;
private Date date;
private Location loc;
public ImageHolder() {
}
public ImageHolder(String uri, Date date, Location loc) {
this.uri = uri;
this.date = date;
this.loc = loc;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Location getLoc() {
return loc;
}
public void setLoc(Location loc) {
this.loc = loc;
}
#Override
public String toString() {
return "ImageHolder{" +
"uri=" + uri +
", date=" + date +
", loc=" + loc +
'}';
}
}
Create a Container class
public class Container implements Serializable {
private ArrayList<ImageHolder> list;
public Container() {
}
public Container(ArrayList<ImageHolder> list) {
this.list = list;
}
public ArrayList<ImageHolder> getList() {
return list;
}
public void setList(ArrayList<ImageHolder> list) {
this.list = list;
}
#Override
public String toString() {
return "Container{" +
"list=" + list +
'}';
}
}
Your First Activity
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
#Override
protected void onPostCreate(#Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
ImageHolder imageHolder0 = new ImageHolder("http://www.stackoverflow.com", new Date(), new Location("test0"));
ImageHolder imageHolder1 = new ImageHolder("http://www.google.com", new Date(), new Location("test1"));
ArrayList<ImageHolder> list = new ArrayList<>();
list.add(imageHolder0);
list.add(imageHolder1);
Container container = new Container(list);
Gson gson = new Gson();
String json = gson.toJson(container);
Intent intent = new Intent(MainActivity.this, TestActivity.class);
intent.putExtra("yourKey", json);
startActivity(intent);
}
}
Your second activity
public class TestActivity extends AppCompatActivity {
public static final String TAG = TestActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onPostCreate(#Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
Gson gson = new Gson();
Container container = gson.fromJson(getIntent().getStringExtra("yourKey"), Container.class);
Log.d(TAG, "OK?" + container.getList().toString());
// Here convert String uri Fields to Uri Objects
// Example:
Uri uri = Uri.parse(container.getList().get(0).getUri());
}
}
Logcat result: 08-01 11:10:22.097 6671-6671/it.darksurfer.english.template D/TestActivity: OK?[ImageHolder{uri=http://www.stackoverflow.com, date=Wed Aug 01 11:10:21 GMT+02:00 2018, loc=Location[test0 0,000000,0,000000 acc=??? t=?!? et=?!?]}, ImageHolder{uri=http://www.google.com, date=Wed Aug 01 11:10:21 GMT+02:00 2018, loc=Location[test1 0,000000,0,000000 acc=??? t=?!? et=?!?]}]
Obviously you can put an undefined number of others ArrayList in the list of Container class!

Related

Passing data in recycler view from API

I tried to make a covid-19 tracking app by watching Youtube tutorials.
My app shows the country list with flags and when you click on any country it opens an activity and shows the details of that country i.e total cases, deaths, recovered, etc. The video on Youtube uses ListView and I am using recyclerView
I fetched the country list successfully and set onClickListener on the view and it opens second activity which shows the case in detail. But I don't know how to show the data.
my adapter class:
class Countries_adapter extends RecyclerView.Adapter<Countries_adapter.MyViewHolder> {
Context ct;
List<Countries_data> list;
public Countries_adapter(Context context,List<Countries_data> country)
{
ct=context;
list=country;
}
#Override
public MyViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
View v = LayoutInflater.from(ct).inflate(R.layout.countries_row,parent,false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.tvCountryName.setText(list.get(position).getCountry());
holder.tvtotal.setText(list.get(position).getActive());
Glide.with(ct).load(list.get(position).getFlag()).into(holder.imageView);
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(ct,CountriesDetails.class);
i.putExtra("Country",list.get(position).getCountry());
ct.startActivity(i);
}
});
}
#Override
public int getItemCount() {
return list.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView tvCountryName,tvtotal;
ImageView imageView;
LinearLayout linearLayout;
public MyViewHolder( View itemView) {
super(itemView);
tvCountryName = itemView.findViewById(R.id.tvCountryName);
tvtotal=itemView.findViewById(R.id.tvCountrytotalcaese);
imageView = itemView.findViewById(R.id.imageFlag);
linearLayout=itemView.findViewById(R.id.linear_layout);
}
}
my AffectedCoutries class activity is as follows:
public class AffectedCountries extends AppCompatActivity {
EditText edtSearch;
RecyclerView recyclerView;
SimpleArcLoader simpleArcLoader;
public static ArrayList countryList = new ArrayList<>();
Countries_data countryData;
Countries_adapter CountriesAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_affected_countries);
edtSearch = findViewById(R.id.edtSearch);
recyclerView=findViewById(R.id.recyclerAffectedCountries);
simpleArcLoader = findViewById(R.id.loader);
fetchData();
}
private void fetchData() {
String url = "https://corona.lmao.ninja/v2/countries/";
simpleArcLoader.start();
StringRequest request = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonArray = new JSONArray(response);
for(int i=0;i<jsonArray.length();i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
String countryName = jsonObject.getString("country");
String cases = jsonObject.getString("cases");
String todayCases = jsonObject.getString("todayCases");
String deaths = jsonObject.getString("deaths");
String todayDeaths = jsonObject.getString("todayDeaths");
String recovered = jsonObject.getString("recovered");
String active = jsonObject.getString("active");
String critical = jsonObject.getString("critical");
JSONObject object = jsonObject.getJSONObject("countryInfo");
String flagUrl = object.getString("flag");
countryData = new Countries_data(flagUrl,countryName,cases,todayCases,deaths,todayDeaths,recovered,active,critical);
countryList.add(countryData);
}
CountriesAdapter = new Countries_adapter(AffectedCountries.this,countryList);
recyclerView.setLayoutManager(new LinearLayoutManager(AffectedCountries.this));
recyclerView.setAdapter(CountriesAdapter);
simpleArcLoader.stop();
simpleArcLoader.setVisibility(View.GONE);
} catch (JSONException e) {
e.printStackTrace();
simpleArcLoader.start();
simpleArcLoader.setVisibility(View.GONE);
Toast.makeText(AffectedCountries.this,"catch response", Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
simpleArcLoader.stop();
simpleArcLoader.setVisibility(View.GONE);
Toast.makeText(AffectedCountries.this,"error response", Toast.LENGTH_SHORT).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(request);
}
}
my Countries_data class(model class)
public class Countries_data {
public String country;
public String cases;
public String todayCases;
public String deaths;
public String todayDeaths;
public String recovered;
public String active;
public String critical;
public String flag;
public Countries_data(String flag, String country, String cases, String
todayCases, String deaths, String todayDeaths, String recovered,
String active, String critical) {
this.country = country;
this.cases = cases;
this.todayCases = todayCases;
this.deaths = deaths;
this.todayDeaths = todayDeaths;
this.recovered = recovered;
this.active = active;
this.critical = critical;
this.flag = flag;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCases() {
return cases;
}
public void setCases(String cases) {
this.cases = cases;
}
public String getTodayCases() {
return todayCases;
}
public void setTodayCases(String todayCases) {
this.todayCases = todayCases;
}
public String getDeaths() {
return deaths;
}
public void setDeaths(String deaths) {
this.deaths = deaths;
}
public String getTodayDeaths() {
return todayDeaths;
}
public void setTodayDeaths(String todayDeaths) {
this.todayDeaths = todayDeaths;
}
public String getRecovered() {
return recovered;
}
public void setRecovered(String recovered) {
this.recovered = recovered;
}
public String getActive() {
return active;
}
public void setActive(String active) {
this.active = active;
}
public String getCritical() {
return critical;
}
public void setCritical(String critical) {
this.critical = critical;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
}
my Country_details class
public class CountriesDetails extends AppCompatActivity {
TextView tvCountry, tvCases, tvRecovered,tvdeaths;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_countries_details2);
tvCountry = findViewById(R.id.tvCountry);
tvCases = findViewById(R.id.tvCases);
tvRecovered = findViewById(R.id.tvRecovered);
tvdeaths=findViewById(R.id.tvTotalDeaths);
String positionCountry = getIntent().getStringExtra("Country");
Log.i("country name", positionCountry);
}
}
How to set the data in tvcases?
How can I show the data? Do I have to create a separate recycler view and then fetch the data from the API or can I use my main activity to show the data?
I have some sad information for you: Google Play policy restricts such apps from being published in store... especially when you are showing deaths count. Been there, done that, my app was blocked...
besides above:
you are passing country name in intent:
i.putExtra("Country",list.get(position).getCountry());
but trying to read "position" in details Activity - it will be always 0 (default)
edit due to comments:
pass position of clicked View
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(ct,CountriesDetails.class);
i.putExtra("position", position);
ct.startActivity(i);
}
});
in CountriesDetailss onCreate method receive this position and restore proper Countries_data object from your static countryList array in AffectedCountries
int position = getIntent().getIntExtra("position", 0);
Countries_data country = AffectedCountries.countryList.get(position);
tvCountry.setText(country.getCountry());
that should work, but this isn't best way to store data, in fact its very weak... after downloading data (list of countries) you should store it somehow, e.g. SQLite/Room lib or at least SharedPreferences... then in details activity you should restore int position and using it take proper object from database or preferences, instead of stright from static array
it may be also useful to implement Parcelable inteface to your Countries_data - this will allow to put whole Countries_data object into Intents extras, not only primitive int with position in array. in this case details activity won't even need access to whole array or sql database/preferences, it will get whole object straight from Intents extras

my project has problem saving ArrayList<T> with SharedPreferences

i have a problem which is making me crazy.
i know how to use "SharedPreferences" in android but i dont know where to put it in my project,like onCreate(),onDestroy() or somewhere else.
*i want to save NoteLab.mNotes in NoteListFragment
*Note.java
package notes.com.example.alireza;
public class Note {
public UUID nId;
public Date nDate;
public String nTitle;
public String nDetails;
public Note(){
nId = UUID.randomUUID();
nDate = new Date();
}
public Date getnDate(){
return nDate;
}
public UUID getnUUID(){
return nId;
}
public String getnTitle() {
return nTitle;
}
public void setnTitle(String nTitle) {
this.nTitle = nTitle;
}
public String getnDetails() {
return nDetails;
}
public void setnDetails(String nDetails) {
this.nDetails = nDetails;
}
}
*NoteLab.java
package notes.com.example.alireza;
import android.content.Context;
import java.util.ArrayList;
import java.util.UUID;
class NoteLab {
public static ArrayList<Note> mNotes;
public static NoteLab noteLab;
public Context mAppContext;
private NoteLab(Context AppContext){
mAppContext = AppContext;
mNotes = new ArrayList<Note>();
}
public static NoteLab get(Context context){
if (noteLab == null){
noteLab = new NoteLab(context.getApplicationContext());
}
return noteLab;
}
public static ArrayList<Note> getNotes(){
return mNotes;
}
public static Note getNote(UUID mId){
for (Note n: mNotes){
if (mId == n.getnUUID()){
return n;
}
}
return null;
}
}
*NoteListFragment.java
package notes.com.example.alireza;
public class NoteListFragment extends ListFragment {
Note note;
ArrayList<Note> notes;
public static Date date;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
notes = NoteLab.get(getActivity()).getNotes();
myArrayAdapter arrayAdapter = new myArrayAdapter(notes);
setListAdapter(arrayAdapter);
}
#Override
public void onStart() {
super.onStart();
View emptyView = getActivity().getLayoutInflater().inflate(R.layout.emptymainlist,null);
((ViewGroup)getListView().getParent()).addView(emptyView);
getListView().setEmptyView(emptyView);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
int checked = 1;
Note c = ((myArrayAdapter)getListAdapter()).getItem(position);
Intent i = new Intent(getActivity(),NoteActivity.class);
i.putExtra("id",c.getnUUID());
i.putExtra(NoteListActivity.EXTRA_DATE,checked);
startActivity(i);
}
//custom arrayList
public class myArrayAdapter extends ArrayAdapter<Note> {
public myArrayAdapter(ArrayList<Note> notes) {
super(getActivity(), 0, notes);
}
#SuppressLint("SetTextI18n")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.notelistfragment_item, null);
}
Note n = getItem(position);
date = n.getnDate();
PersianCalendar persianCalendar = new PersianCalendar();
persianCalendar.setTime(date);
TextView titleTextView = convertView.findViewById(R.id.titleTextView);
titleTextView.setText(n.getnTitle());
TextView detailTextView = convertView.findViewById(R.id.detailsTextView);
detailTextView.setText(n.getnDetails());
TextView dateTextView = convertView.findViewById(R.id.dateTextView);
dateTextView.setText(DateFormat.getDateInstance(DateFormat.FULL).format(date) + " : تاریخ ذخیره ");
return convertView;
}
}
#Override
public void onResume() {
super.onResume();
((myArrayAdapter)getListAdapter()).notifyDataSetChanged();
}
as you understand from the codes, i want to save my mNotes arrayList which is placed in NoteLab.java.there is NoteListActivtiy.java too which is supporting NoteListFragment but i think this can be done in NoteListFragment.
thanks to stackoverflow and everyone who tryes to help me.
You can use Gson library to convert what you want to String then you can get it back again.
Where should you put your code ?? it depends on your business (or requirements).
If you want to pass your array of items to fragment or another activity you can use Gson lib to convert it to string then put it into bundle and pass this bundle to whatever you want. Then in the fragment or the activity you can get this array by Gson also.
Here is an example:
Gson gson = new Gson();
gson.toSring(yourData);
// then you can get the data by
Gson gson = new Gson();
String data = yourBundle.getString("your_key");
yourDataModel = gson.fromJson(data, YourDataModel.class);
// it will work even with ArrayList

AsyncTask - missing something [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm doing some project and I'm stuck ... I'm doing something wrong, probably with AsyncTask and I have no idea what to fix and how .... there is code I have right now.
ReviewData.class
public class ReviewData implements Parcelable {
private String mAuthor, mContent;
public ReviewData(String author, String content) {
this.mAuthor = author;
this.mContent = content;
}
private ReviewData(Parcel in) {
mAuthor = in.readString();
mContent = in.readString();
}
public static final Creator<ReviewData> CREATOR = new Creator<ReviewData>() {
#Override
public ReviewData createFromParcel(Parcel in) {
return new ReviewData(in);
}
#Override
public ReviewData[] newArray(int size) {
return new ReviewData[size];
}
};
//Getter method for review author
public String getAuthor() {
return mAuthor;
}
//Setter method for review author
public void setAuthor(String author) {
this.mAuthor = author;
}
//Getter method for review content
public String getContent() {
return mContent;
}
//Setter method for review content
public void setContent(String content) {
this.mContent = content;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mAuthor);
dest.writeString(mContent);
}
}
ReviewAdapter.class
public class ReviewAdapter extends RecyclerView.Adapter<ReviewAdapter.ReviewViewHolder> {
private ArrayList<ReviewData> mReviewList;
private Context mContext;
public ReviewAdapter(Context context, ArrayList<ReviewData> reviewList) {
this.mContext = context;
this.mReviewList = reviewList;
}
#Override
public ReviewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
mContext = parent.getContext();
View view = LayoutInflater.from(mContext).inflate(R.layout.review_item_list,
parent, false);
view.setFocusable(true);
return new ReviewViewHolder(view);
}
#Override
public void onBindViewHolder(final ReviewViewHolder holder, int position) {
if(mReviewList != null) {
ReviewData reviewData = mReviewList.get(position);
holder.reviewAuthor.setText(reviewData.getAuthor());
holder.reviewContent.setText(reviewData.getContent());
}
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemCount() {
if(mReviewList == null) {
return 0;
} else {
return mReviewList.size();
}
}
public void setReviewList(ArrayList<ReviewData> reviewList) {
if(reviewList != null) {
mReviewList = new ArrayList<>(reviewList);
}
notifyDataSetChanged();
}
public class ReviewViewHolder extends RecyclerView.ViewHolder {
TextView reviewAuthor;
TextView reviewContent;
public ReviewViewHolder(View itemView) {
super(itemView);
reviewAuthor = itemView.findViewById(R.id.review_author);
reviewContent = itemView.findViewById(R.id.review_content);
}
}
}
NetworkUtils.class (but only code for Review url builder, for other thing works perfectly). PS. this parse is written as API documentation said ... it should be someurl/movie/{id}/reviews
//URL builder for reviews
public static URL buildReviewUrl(String id) {
Uri builtUri = Uri.parse(BASE_MOVIE_URL + id + REVIEW).buildUpon()
.appendQueryParameter(QUERY_API_KEY, API_KEY)
.build();
URL url = null;
try {
url = new URL(builtUri.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
}
return url;
}
JsonData. class (also, only for Reviews, for other works perfectly...)
//JSON for Review
public static ArrayList<ReviewData> getReviewFromJson(String json) throws JSONException {
ArrayList<ReviewData> listOfReviews = new ArrayList<>();
try {
JSONObject reviews = new JSONObject(json);
JSONArray reviewsArray = reviews.getJSONArray(QUERY_RESULTS);
for(int i = 0; i < reviewsArray.length(); i++) {
JSONObject jsonReview = reviewsArray.getJSONObject(i);
String author = jsonReview.optString(REVIEW_AUTHOR);
String content = jsonReview.optString(REVIEW_CONTENT);
ReviewData reviewData = new ReviewData(author, content);
listOfReviews.add(reviewData);
}
} catch(JSONException e) {
e.printStackTrace();
Log.e("ReviewJson", "JSON Review Error");
}
return listOfReviews;
}
ReviewAsyncTask.class
public class ReviewAsyncTask extends AsyncTask<String, Void, ArrayList<ReviewData>> {
private ReviewData mReviewData;
public interface ReviewResponse {
void finished(ArrayList<ReviewData> output);
}
private ReviewResponse reviewResponse = null;
public ReviewAsyncTask(ReviewResponse reviewResponse) {
this.reviewResponse = reviewResponse;
}
#Override
protected ArrayList<ReviewData> doInBackground(String... strings) {
String rawData = "";
ArrayList<ReviewData> reviewList = new ArrayList<>();
try {
rawData = NetworkUtils.getResponseFromHttpRequest(NetworkUtils
.buildReviewUrl(String.valueOf(mReviewData)));
reviewList = JsonData.getReviewFromJson(rawData);
} catch (IOException e) {
e.printStackTrace();
Log.e("ReviewAsyncTask", "Error in ReviewAsyncTask");
} catch (JSONException e) {
e.printStackTrace();
Log.e("JSONAsync", "JSON problem");
}
return reviewList;
}
#Override
protected void onPostExecute(ArrayList<ReviewData> reviewData) {
reviewResponse.finished(reviewData);
}
}
and MovieDetails activity (everything works fine except from the comment recycle review to next comment.
public class MovieDetails extends AppCompatActivity implements ReviewAsyncTask.ReviewResponse {
private final static String BASE_URL = "http://image.tmdb.org/t/p/";
private final static String SIZE = "w185/";
private ArrayList<ReviewData> mReviewList;
private ReviewAdapter mReviewAdapter;
#BindView(R.id.poster_detail)
ImageView mMoviePoster;
#BindView(R.id.title_detail)
TextView mMovieTitle;
#BindView(R.id.release_date)
TextView mReleaseDate;
#BindView(R.id.average_vote)
TextView mAverageVote;
#BindView(R.id.synopsis)
TextView mSynopsis;
#BindView(R.id.review_recycler)
RecyclerView mReviewRecycle;
Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_details);
ButterKnife.bind(this);
displayMovieDetail();
//Review RecycleView
mReviewList = new ArrayList<>();
mReviewAdapter = new ReviewAdapter(this, mReviewList);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
mReviewRecycle.setLayoutManager(layoutManager);
mReviewRecycle.setHasFixedSize(true);
mReviewRecycle.setAdapter(mReviewAdapter);
}
#Override
public void finished(ArrayList<ReviewData> output) {
ReviewAsyncTask reviewAsyncTask = new ReviewAsyncTask(this);
reviewAsyncTask.execute();
}
/* Method for displaying the info about movies in activity details
* #param mMoviePoster sets the movie poster
* #param mMovieTitle sets original title of the movie
* #param mReleaseDate sets release date of the movie
* #param mAverageVote sets average rating grade of the movie
* #param mSynopsis sets plot of the movie */
private void displayMovieDetail() {
int idMovie = (Integer) getIntent().getExtras().get(getString(R.string.movie_id));
List<MovieData> movieList;
movieList = getIntent().getParcelableArrayListExtra(getString(R.string.movie_lsit));
MovieData movieData = movieList.get(idMovie);
Picasso.with(mContext).load(BASE_URL + SIZE +
movieData.getPoster()).into(mMoviePoster);
mMovieTitle.setText(movieData.getTitle());
mReleaseDate.setText(movieData.getReleaseDate());
mAverageVote.setText(Double.toString(movieData.getRating()));
mSynopsis.setText(movieData.getSynopsis());
}
}
P.S. I would share github link but I should give you my personal API key. :(
You need to start the AsyncTask in onCreate() (like you did before) and in finished() you take the results and add them to the Adapter's data list.
Finally, don't forget to call notifyDatasetChanged().
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_details);
// skipping some lines of code here...
mReviewRecycle.setAdapter(mReviewAdapter);
ReviewAsyncTask reviewAsyncTask = new ReviewAsyncTask(this);
reviewAsyncTask.execute();
}
#Override
public void finished(ArrayList<ReviewData> output) {
mReviewList.addAll(output);
mReviewAdapter.notifyDatasetChanged();
}
(Please note that I skipped null checks and error handling for brevity's sake)
In MovieDetails onCreate retrieve current movie ID like you do in displayMovieDetail.
Send that ID to ReviewAsyncTask (you'll need to modify constructor of ReviewAsyncTask)
Retrieve id in ReviewAsyncTask, save it as member variable, and then in doInBackground method send that id to buildReviewUrl as an argument.

Splash Screen using AsyncTask

I have a splash screen using AsyncTask, it will download some data from database and store the data in ArrayList. This ArrayList will be used for RecyclerView in fragments of MainActivity.class.
The problem is when I run the app from Android Studio to my phone, everything works perfectly. But, when I destroy the app and run it manually from my phone it will display blank white screen and then it will crash. And if I run once again after it crashed, the app will work. So, this app will always work only if I run it from Android Studio or after it crashed.
The error says that it is caused by the empty list. If I'm not mistaken, I think the AsyncTask doesn't seem to work properly after the activity is destroyed. But I don't know how to fix it. Please help me to solve this problem.
SplashScreen.java
public class SplashScreenActivity extends AppCompatActivity {
public static Event event;
private static List<Feed> feedList;
private static List<Event> eventList;
private static List<Event> todayList;
private static List<Event> upcomingList;
private static List<Partner> partnerList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splashscreen);
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
Config.TODAY_DATE = String.valueOf(today.monthDay) + "-" + String.valueOf(today.month) + "-" + String.valueOf(today.year);
new DownloadData().execute("");
}
class DownloadData extends AsyncTask<String, Integer, String>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
startActivity(new Intent(getBaseContext(), WelcomeActivity.class));
finish();
}
#Override
protected String doInBackground(String... params) {
RequestHandler rh = new RequestHandler();
String JSON_STRING = rh.sendGetRequest(Config.URL_GET_ALL_DATA);
JSONObject jsonObject;
eventList = new ArrayList<>();
todayList = new ArrayList<>();
upcomingList = new ArrayList<>();
partnerList = new ArrayList<>();
feedList = new ArrayList<>();
try {
jsonObject = new JSONObject(JSON_STRING);
JSONArray getEvent = jsonObject.getJSONArray(Config.TAG_JSON_EVENT);
for (int i = 0; i < getEvent.length(); i++) {
int id = getEvent.getJSONObject(i).getInt(Config.TAG_ID);
int eoId = getEvent.getJSONObject(i).getInt(Config.TAG_EO_ID);
String eoName = getEvent.getJSONObject(i).getString(Config.TAG_EO_NAME);
String title = getEvent.getJSONObject(i).getString(Config.TAG_TITLE);
String day = getEvent.getJSONObject(i).getString(Config.TAG_DAY);
String date = getEvent.getJSONObject(i).getString(Config.TAG_DATE);
int price = getEvent.getJSONObject(i).getInt(Config.TAG_PRICE);
event = new Event(id, eoId, eoName, title, day, date, price);
eventList.add(event);
if(Config.TODAY_DATE.equals(event.getDate())){
todayList.add(event);
} else {
upcomingList.add(event);
}
}
JSONArray getPartner = jsonObject.getJSONArray(Config.TAG_JSON_PARTNER);
for (int i = 0; i < getPartner.length(); i++) {
int pId = getPartner.getJSONObject(i).getInt(Config.TAG_ID);
String pName = getPartner.getJSONObject(i).getString(Config.TAG_NAME);
String pEmail = getPartner.getJSONObject(i).getString(Config.TAG_EMAIL);
String pPhone = getPartner.getJSONObject(i).getString(Config.TAG_PHONE);
String pPhoto = getPartner.getJSONObject(i).getString(Config.TAG_PHOTO_URL);
Partner partner = new Partner(pId, pName, pEmail, pPhone, pPhoto);
partnerList.add(partner);
}
JSONArray getArticle = jsonObject.getJSONArray(Config.TAG_JSON_ARTICLE);
for (int i = 0; i < getArticle.length(); i++) {
int feedId = getArticle.getJSONObject(i).getInt(Config.TAG_ID);
String feedAuthor = getArticle.getJSONObject(i).getString(Config.TAG_FEED_AUTHOR);
String feedTitle = getArticle.getJSONObject(i).getString(Config.TAG_FEED_TITLE);
String feedContent = getArticle.getJSONObject(i).getString(Config.TAG_FEED_CONTENT);
String feedDate = getArticle.getJSONObject(i).getString(Config.TAG_FEED_DATE);
String feedThumbnail = getArticle.getJSONObject(i).getString(Config.TAG_FEED_THUMBNAIL);
Feed feed = new Feed(feedId, feedAuthor, feedTitle, feedContent, feedDate, feedThumbnail);
feedList.add(feed);
}
} catch (JSONException e) {
e.printStackTrace();
}
return JSON_STRING;
}
}
public static List<Feed> getFeedList(){ return feedList;}
public static List<Event> getEventList() {return eventList;}
public static List<Event> getTodayList() { return todayList;}
public static List<Event> getUpcomingList() { return upcomingList;}
public static List<Partner> getPartnerList() {return partnerList;}
}
DiscoverFragment.java
public class DiscoverFragment extends Fragment implements ViewPager.OnPageChangeListener, View.OnClickListener {
protected View view;
private LinearLayout pager_indicator;
private int dotsCount;
private ImageView[] dots;
private List<Feed> feedList;
private List<Event> eventList;
private List<Partner> partnerList;
public DiscoverFragment() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_discover, container, false);
RecyclerView recyclerViewEvent = (RecyclerView) view.findViewById(R.id.discover_event_recycler_view);
RecyclerView recyclerViewPartner = (RecyclerView) view.findViewById(R.id.discover_partner_recycler_view);
ClickableViewPager intro_images = (ClickableViewPager) view.findViewById(R.id.pager_introduction);
pager_indicator = (LinearLayout) view.findViewById(R.id.viewPagerCountDots);
eventList = SplashScreenActivity.getEventList();
partnerList = SplashScreenActivity.getPartnerList();
feedList = SplashScreenActivity.getFeedList();
EventAdapter eventAdapter = new EventAdapter(getContext(), eventList);
DiscoverPartnerAdapter discoverPartnerAdapter = new DiscoverPartnerAdapter(getContext(), partnerList);
DiscoverFeedAdapter mAdapter = new DiscoverFeedAdapter(getContext(), feedList);
final LinearLayoutManager layoutManagerEvent = new LinearLayoutManager(getContext());
final LinearLayoutManager layoutManagerPartner = new LinearLayoutManager(getContext());
layoutManagerEvent.setOrientation(LinearLayoutManager.HORIZONTAL);
layoutManagerPartner.setOrientation(LinearLayoutManager.HORIZONTAL);
addBottomDots(0);
intro_images.setAdapter(mAdapter);
intro_images.setCurrentItem(0);
intro_images.addOnPageChangeListener(this);
intro_images.setOnItemClickListener(new ClickableViewPager.OnItemClickListener() {
#Override
public void onItemClick(int position) {
Config.FEED_ID = position;
startActivity(new Intent(getContext(), ArticleActivity.class));
}
});
return view;
}
private void addBottomDots(int currentPage) {
dots = new ImageView[feedList.size()]; //the problem
pager_indicator.removeAllViews();
for (int i = 0; i < dots.length; i++) {
dots[i] = new ImageView(getContext());
dots[i].setImageDrawable(getResources().getDrawable(R.drawable.nonselecteditem_dot));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(4, 0, 4, 0);
pager_indicator.addView(dots[i], params);
}
if (dots.length > 0)
dots[currentPage].setImageDrawable(getResources().getDrawable(R.drawable.selecteditem_dot));
}
#Override
public void onClick(View v) {
switch (v.getId()) {
}
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
addBottomDots(position);
for (int i = 0; i < dotsCount; i++) {
dots[i].setImageDrawable(getResources().getDrawable(R.drawable.nonselecteditem_dot));
}
dots[position].setImageDrawable(getResources().getDrawable(R.drawable.selecteditem_dot));
}
}
LogCat
01-29 00:40:57.565 32535-32535/com.irmaelita.esodiaapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.irmaelita.esodiaapp, PID: 32535
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at com.irmaelita.esodiaapp.fragment.DiscoverFragment.addBottomDots(DiscoverFragment.java:181)
at com.irmaelita.esodiaapp.fragment.DiscoverFragment.onCreateView(DiscoverFragment.java:158)
feedList is null. You create feedList instance when DownloadData task is executed. But you call feedList.size() in addBottomDots when fragment view should be created. So, most probably addBottomDots is called before DownloadData task is executed. You need to fix it.
The feedlist in your discover fragment is going empty while initializing. Please set a null check before doing so.It not about running from android studio.If I have understood it correctly you are trying to access a list from splasScreen activity after finishing it. ie in post execute you finish the current activity and the fragment is in main activity,so the list is going null.So if this is the case (and please correct me if not) then either download the data somewhere centrally or best way send it to main activity with intent and use it there. Also when running from android studio kill the app manually and run it again,while the phone is connected and see if it crashes in current scenario.
Send your data from doInBackground to MainActivity with sendBroadcast
Add broadcast method in DownloadData class
private void broadcast(SplashParcel parcel) {
Intent i = new Intent("splash_parcel");
i.putExtra("values", parcel);
sendBroadcast(i);
}
#Override
protected String doInBackground(String... params) {
// your code
// ..
try {
// your code
// ..
// send splashParcel to MainActivity
SplashParcel splashParcel = new SplashParcel(feedList, eventList, todayList, upcomingList, partnerList);
broadcast (splashParcel);
} catch (JSONException e) {
e.printStackTrace();
}
return JSON_STRING;
}
Add new class SplashParcel.java
public class SplashParcel implements Parcelable {
public static final Creator<SplashParcel> CREATOR = new Creator<SplashParcel>() {
#Override
public SplashParcel createFromParcel(Parcel in) {
return new SplashParcel(in);
}
#Override
public SplashParcel[] newArray(int size) {
return new SplashParcel[size];
}
};
private static List<Feed> _feedList;
private static List<Event> _eventList;
private static List<Event> _todayList;
private static List<Event> _upcomingList;
private static List<Partner> _partnerList;
protected SplashParcel(Parcel in) {
_feedList = new ArrayList<Feed>();
in.readList(_feedList, null);
_eventList = new ArrayList<Event>();
in.readList(_eventList, null);
_todayList = new ArrayList<Event>();
in.readList(_todayList, null);
_upcomingList = new ArrayList<Event>();
in.readList(_upcomingList, null);
_partnerList = new ArrayList<Partner>();
in.readList(_partnerList, null);
}
public SplashParcel(List<Feed> feedList, List<Event> eventList, List<Event> todayList, List<Event> upcomingList, List<Partner> partnerList) {
_feedList = feedList;
_eventList = eventList;
_todayList = todayList;
_upcomingList = upcomingList;
_partnerList = partnerList;
}
public SplashParcel() {
}
public List<Feed> getFeedList() {
return _feedList;
}
public void setFeedList(List<Feed> feedList) {
_feedList = feedList;
}
public List<Event> getEventList() {
return _eventList;
}
public void setEventList(List<Event> eventList) {
_eventList = eventList;
}
public List<Event> getTodayList() {
return _todayList;
}
public void setTodayList(List<Event> todayList) {
_todayList = todayList;
}
public List<Event> getUpcomingList() {
return _upcomingList;
}
public void setUpcomingList(List<Event> upcomingList) {
_upcomingList = upcomingList;
}
public List<Partner> getPartnerList() {
return _partnerList;
}
public void setPartnerList(List<Partner> partnerList) {
_partnerList = partnerList;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeList(_feedList);
parcel.writeList(_eventList);
parcel.writeList(_todayList);
parcel.writeList(_upcomingList);
parcel.writeList(_partnerList);
}
}
MainActivity.java
// member variable
private BroadcastReceiver _splashReceiver;
private Bundle _bundle = new Bundle();
#Override
protected void onResume() {
super.onResume();
splashReceiver();
}
// receive splashParcel from SplashScreenActivity
private void splashReceiver() {
if (_splashReceiver == null) {
_splashReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
SplashParcel splashParcel = intent.getParcelableExtra("values");
if (splashParcel != null) {
// save splashParcel into _budle
_bundle.putParcelable("splash_parcel", splashParcel);
}
}
};
registerReceiver(_splashReceiver, new IntentFilter("splash_parcel"));
}
}
//Send _bundle to DiscoverFragment
private void showDiscoverFragment(){
if(_bundle != null) {
// create instance of discoverFragment with passing _bundle as arguments
DiscoverFragment discoverFragment = new DiscoverFragment();
discoverFragment.setArguments(_bundle);
// replace activity_main.xml with discoverFragment
getSupportFragmentManager().beginTransaction().replace(R.id.main_container, discoverFragment).addBackStack(null).commit();
}
}
In onCreateView of DiscoverFragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
SplashParcel splashParcel = getArguments().getParcelable("splash_parcel");
if(splashParcel != null) {
// your splashParcel ready in here
List<Feed> feedList = splashParcel.getFeedList()
List<Event> eventList = splashParcel.getEventList()
List<Event> todayList = splashParcel.getTodayList();
List<Event> upcommingList = splashParcel.getUpcomingList();
List<Partner> partnerList = splashParcel.getPartnerList();
}
}

How can I pass object from ArrayList to new Activity and then receive that? [duplicate]

This question already has answers here:
How to pass ArrayList<CustomeObject> from one activity to another? [duplicate]
(3 answers)
Closed 7 years ago.
I try pass an object to new activity but I have a problem. My ArrayList use another class in this way:
ArrayList<ListData> myList = new ArrayList<>();
All is great, I'm adding to mList a few objects and my listview work fine.
I try pass an object after click in this way:
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
ListData listdata = myList.get(position);
ListData dataToSend = new ListData();
dataToSend.setStrefa(listdata.getStrefa());
dataToSend.setDzielnica(listdata.getDzielnica());
dataToSend.setAdres(listdata.getAdres());
dataToSend.setKryteria(listdata.getKryteria());
dataToSend.setTelefon(listdata.getTelefon());
dataToSend.setData(listdata.getData());
Intent intent = new Intent(Zlecenia.this, Zlecenie.class);
intent.putExtra("myData", dataToSend);
startActivity(intent);
overridePendingTransition(R.anim.fade_in, R.anim.no_animation);
}
});
Here is a problem because "bundle.putParcelableArrayList("listdata", listdata);" is marked on red. This forces on me using extends Parcelable in ListData Class but when I added this extends then my ArrayList is empty. What schould I do?
My ListData:
public class ListData implements Parcelable{
String Strefa;
String Adres;
String Kryteria;
String Telefon;
String Data;
String Dzielnica;
String Ilosc;
/* Zlecenia */
public String getStrefa() {
return Strefa;
}
public void setStrefa(String strefa) {
this.Strefa = strefa;
}
public String getAdres() {
return Adres;
}
public void setAdres(String adres) {
this.Adres = adres;
}
public String getKryteria() {
return Kryteria;
}
public void setKryteria(String kryteria) {
this.Kryteria = kryteria;
}
public String getTelefon() {
return Telefon;
}
public void setTelefon(String telefon) {
this.Telefon = telefon;
}
public String getData() {
return Data;
}
public void setData(String data) {
this.Data = data;
}
/* Statystyki */
public String getDzielnica() {
return Dzielnica;
}
public void setDzielnica(String dzielnica) {
this.Dzielnica = dzielnica;
}
public String getIlosc() {
return Ilosc;
}
public void setIlosc(String ilosc) {
this.Ilosc = ilosc;
}
public ListData() {
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(Strefa);
dest.writeString(Dzielnica);
dest.writeString(Adres);
dest.writeString(Kryteria);
dest.writeString(Telefon);
dest.writeString(Data);
}
private ListData(Parcel in) {
Strefa = in.readString();
Dzielnica = in.readString();
Adres = in.readString();
Kryteria = in.readString();
Telefon = in.readString();
Data = in.readString();
}
public static final Parcelable.Creator<ListData> CREATOR
= new Parcelable.Creator<ListData>() {
#Override
public ListData createFromParcel(Parcel in) {
return new ListData(in);
}
#Override
public ListData[] newArray(int size) {
return new ListData[size];
}
};
}
Try this in your class
public class ListData implements Serializable

Categories

Resources