Im using this library https://github.com/stepstone-tech/android-material-stepper
for accomodating multiple fragments in a single activity. In one of the fragments, I was trying to save the item objects in the fragments recyclerview in onSaveInstanceState() method,it works quite alright but when the app loses focus(such as pressing home button),the app crashes(it works well when i exit the app by pressing the back button).
Here is the fragment
public class StylesFragment extends Fragment implements Step {
private static final String STATE_ITEMS = "items";
RecyclerView recyclerView;
private TAASService mService;
public ArrayList<CustomStyles> styles;
public StylesFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
#SuppressWarnings("unchecked")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View v=inflater.inflate(R.layout.fragment_styles, container, false);
recyclerView=(RecyclerView) v.findViewById(R.id.recycler);
//recyclerView.setAdapter(adapter);
mService = ApiUtils.getTAASService();
if (savedInstanceState==null) {
loadCustomStyles();
}else{
styles = (ArrayList<CustomStyles>) savedInstanceState.getSerializable(STATE_ITEMS);
StylesListAdapter adapter = new StylesListAdapter(styles);
//do more things
}
return v;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(STATE_ITEMS,styles);
}
public void loadCustomStyles() {
//load from network
}
So I noticed on removing outState.putSerializable(); .It does not crash the app when the app loses focus,anyone know what is happening here and how i can correct it?Thank you
PS:The laptop I use for coding android is of low quality,so I cant make use of the logcat.Have to assemble,install on my phone,to see how it works.
UPDATE
public class CustomStyles implements Serializable{
#SerializedName("pk")
#Expose
private Integer pk;
#SerializedName("name")
#Expose
private String name;
#SerializedName("gender")
#Expose
private String gender;
#SerializedName("photo1")
#Expose
private String photo1;
#SerializedName("custom_price")
#Expose
private Integer customPrice;
#SerializedName("designer")
#Expose
private Designer designer;
public Integer getPk() {
return pk;
}
public void setPk(Integer pk) {
this.pk = pk;
}
public String getName() {
return name;
}
#Override
public String toString() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPhoto1() {
return photo1;
}
public void setPhoto1(String photo1) {
this.photo1 = photo1;
}
public Integer getCustomPrice() {
return customPrice;
}
public void setCustomPrice(Integer customPrice) {
this.customPrice = customPrice;
}
public Designer getDesigner() {
return designer;
}
public void setDesigner(Designer designer) {
this.designer = designer;
}
}
Your CustomStyles class is not serializable
Implement serializable in you class CustomStyles (and also in all custom classes you are using inside CustomStyles class)
public class CustomStyles implements Serializable {
.
.
.
.
}
Related
i have facing issue like only two items are displayed others two items are not displayed they are contact and flat no this items are not displaying...i tried also removing and adding others textview but through this only two items are displayed.... Now I want to display the data on a RecyclerView which doesn't seem to work, I'm pretty sure that my code is good but something doesn't seem to work and I can't find it.i also try all the things suggested by stackoverflow but nothing can happen so that i think i need to ask...
Here the file
public class RecieptFP extends AppCompatActivity {
private RecyclerView mFirestoreList;
private FirebaseFirestore firebasefirestore;
private FirestoreRecyclerAdapter adapter;
Button Back;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reciept_fp);
Back = findViewById(R.id.btndashboard);
firebasefirestore = FirebaseFirestore.getInstance();
mFirestoreList = findViewById(R.id.firestore_list);
//query
Query query = firebasefirestore.collection("UserDataR");
//RecyclerOptions
FirestoreRecyclerOptions<RecieptModel> options = new FirestoreRecyclerOptions.Builder<RecieptModel>()
.setQuery(query, RecieptModel.class)
.build();
adapter = new FirestoreRecyclerAdapter<RecieptModel, RecieptViewHolder>(options) {
#NonNull
#Override
public RecieptViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listsingleiteam, parent, false);
return new RecieptViewHolder(view);
}
#Override
protected void onBindViewHolder(RecieptViewHolder recieptViewHolder, int i, RecieptModel recieptModel) {
recieptViewHolder.list_name.setText(recieptModel.getName());
recieptViewHolder.list_amount.setText(recieptModel.getAmount());
recieptViewHolder.list_contact.setText(recieptModel.getContact());
recieptViewHolder.list_Flatno.setText(recieptModel.getFlatNo());
}
};
//viewholder
mFirestoreList.setHasFixedSize(false);
mFirestoreList.setLayoutManager(new LinearLayoutManager(this));
mFirestoreList.setAdapter(adapter);
Back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i1 = new Intent(RecieptFP.this, Dashboard.class);
startActivity(i1);
}
});
}
private class RecieptViewHolder extends RecyclerView.ViewHolder {
private TextView list_name;
private TextView list_amount;
private TextView list_contact;
private TextView list_Flatno;
public RecieptViewHolder(#NonNull View itemView) {
super(itemView);
list_name = itemView.findViewById(R.id.list_name);
list_amount = itemView.findViewById(R.id.list_amount);
list_contact = itemView.findViewById(R.id.list_contact);
list_Flatno = itemView.findViewById(R.id.list_Flatno);
}
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
}
Recipet Model
package com.societypay;
public class RecieptModel {
private String Name;
private String Amount;
private String Contact;
private String FlatNo;
private RecieptModel(){}
private RecieptModel(String Name,String Amount,String Contact,String FlatNo){
this.Name=Name;
this.Amount=Amount;
this.Contact=Contact;
this.FlatNo=FlatNo;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getAmount() {
return Amount;
}
public void setAmount(String amount) {
Amount = amount;
}
public String getContact() {
return Contact;
}
public void setContact(String contact) {
Contact = contact;
}
public String getFlatNo() {
return FlatNo;
}
public void setFlatNo(String flatNo) {
FlatNo = flatNo;
}
}
Please use following pojo and try.
public class RecieptModel
{
private String MobileNo;
private String Amount;
private String Flat_no;
private String Name;
public String getMobileNo ()
{
return MobileNo;
}
public void setMobileNo (String MobileNo)
{
this.MobileNo = MobileNo;
}
public String getAmount ()
{
return Amount;
}
public void setAmount (String Amount)
{
this.Amount = Amount;
}
public String getFlat_no ()
{
return Flat_no;
}
public void setFlat_no (String Flat_no)
{
this.Flat_no = Flat_no;
}
public String getName ()
{
return Name;
}
public void setName (String Name)
{
this.Name = Name;
}
#Override
public String toString()
{
return "ClassPojo [MobileNo = "+MobileNo+", Amount = "+Amount+", Flat_no = "+Flat_no+", Name = "+Name+"]";
}
}
I am currently building an app to retrieve information for a remote server. the data received are JSON and I am build a list of Data using the class below :
public class RedditData {
private RedditTopic data;
public RedditTopic getData() {
return data;
}
}
and RedditTopic class is defined as below:
public final class RedditTopic {
private static final String TAG = RedditTopic.class.getSimpleName();
private String author;
private String thumbnail;
private String title;
private String num_comments;
private long created_utc;
private String data;
private String name;
public RedditTopic(){};
public String getData() {
return data;
}
public String getAuthor() {
return author;
}
public String getThumbnail(){
return thumbnail;
}
public String getTitle(){
return title;
}
public String getComments(){
return num_comments + " comments";
}
public long getCreated_utc(){
return created_utc;
}
public String getRedditName(){
return name;
}
}
both of these classes are used to translate a JSON into an Object formatted data.
I do not want to really change them to make them Parceable to avoid impacting the extraction of JSON.
I have added :
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
Log.d(TAG, ">>>>>>>>>>>>>>>>>>>>>>>> SAVE");
savedInstanceState.putParcelableArrayList("RedditList", myListOfData );
super.onSaveInstanceState(savedInstanceState);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, ">>>>>>>>>>>>>>>>>>>>>>>> RESTORE");
List<RedditData> myListOfData = savedInstanceState.getParcelableArrayList("RedditList");
}
Android complain because I need to implement Parceable in my class RedditData and I assume probably in the RedditTopic Class as well because RedditData returned a List of RedditTopic.
Is there a better way to do it? keep the List as I have it without requiring the Parceable option.
I do not have a List of String, it's a list of object.
Any idea?
Regards
Make your model objects parcleable.
There is a great extension, https://plugins.jetbrains.com/plugin/7332-android-parcelable-code-generator that will generate the neccesary parcelable methods for your class.
I highly recommend it.
I am try to parse this Json array from this site NewsApi and display it in a listView.When I run the app nothing is displaying.Here is my code.What am doing wrong?.I have tried to debug the problem to no avail.
public class NewsApiClient {
public static String API_BASE_URL = "https://newsapi.org/v1/";
public static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
public static Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create()
);
public static Retrofit retrofit = builder.client(httpClient.build()).build();
NewsApiClient client = retrofit.create(NewsApiClient.class);
}
calling the endpoint?
public interface NewsApiInterface {
//endpoint
#GET("sources")
Call <SourcesResponse> getTechSources(
#Query("language") String language,
#Query("category") String category)
}
I am only using the name,description and category attributes.
public class Source {
#SerializedName("id")
public String id;
#SerializedName("name")
public String name;
#SerializedName("description")
public String description;
#SerializedName("url")
public String url;
#SerializedName("category")
public String category;
#SerializedName("language")
public String language;
#SerializedName("country")
public String country;
}
public class SourcesAdapter extends BaseAdapter {
Context context;
List<Source> sourceList;
public SourcesAdapter( Context context,List<Source> sourceList){
this.context = context;
this.sourceList = sourceList;
}
#Override
public int getCount() {
return sourceList.size();
}
#Override
public Object getItem(int position) {
return sourceList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
convertView = layoutInflater.inflate(R.layout.sources_list,null);
Source currentsource = sourceList.get(position);
TextView sourcesName = (TextView) convertView.findViewById(R.id.sources_name);
TextView sourcesDescription = (TextView) convertView.findViewById(R.id.sources_description);
TextView sourcesCategory = (TextView) convertView.findViewById(R.id.sources_category);
sourcesName.setText(currentsource.name);
sourcesDescription.setText(currentsource.description);
sourcesCategory.setText(currentsource.category);
return convertView;
}
}
public class SourcesFragment extends Fragment {
ListView listView;
public SourcesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
//
//instance of the adapter to this listview
View view = inflater.inflate(R.layout.fragment_sources, container, false);
listView = (ListView)view.findViewById(R.id.list_view_sources) ;
getSources();
return view;
}
public void getSources(){
Retrofit retrofit = NewsApiClient.builder.build();
NewsApiInterface newsApiInterface = retrofit.create(NewsApiInterface.class);
Call<SourcesResponse> sourcesCall = newsApiInterface.getTechSources("en", "technology");
sourcesCall.enqueue(new Callback<SourcesResponse>() {
#Override
public void onResponse(Call<SourcesResponse> call, Response<SourcesResponse> response) {
List<Source> sources = response.body().sources;
SourcesAdapter sourcesAdapter = new SourcesAdapter(getContext(),sources);
listView.setAdapter(sourcesAdapter);
}
#Override
public void onFailure(Call<SourcesResponse> call, Throwable t) {
}
});
}
}
public class SourcesResponse {
#SerializedName("status")
public String status;
#SerializedName("sources")
public List<Source> sources;
}
I have created 3 fragments,the sources fragment is one of them.On the sources fragment i only want to display sources with technology.
Thank you in advance!
In your retrofit's onResponse callback method, you are accessing sources list like response.body().sources. Instead of this in the SourcesResponse , add a getter and setter for sources like this
public List<SourcesResponse> getSources() {
return sources;
}
public void setSources(List<SourcesResponse> sources) {
this.sources = sources;
}
Now go to your onResponse callback of retrofit and change
response.body().sources
to
response.body().getSources()
In the following Realm example,I created two models. One is called Task and the other User. With the help of Realm I am going to use the one-to-one relationship. ie. User "Theo" has one Task.
So here are my models.
#RealmClass
public class Task implements RealmModel {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#PrimaryKey
private String id;
private String title;
public boolean isCompleted() {
return isCompleted;
}
public void setCompleted(boolean completed) {
isCompleted = completed;
}
private String description;
private boolean isCompleted;
}
And
#RealmClass
public class User implements RealmModel {
#PrimaryKey
private String id;
private String firstName;
private String lastName;
private Task task;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Task getTask() {
return task;
}
public void setTask(Task task) {
this.task = task;
}
}
And in my main fragment I insert dummy data.
public class MainFragment extends Fragment {
private Task task;
private Realm realm;
private TextView textContent;
public MainFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_main, container, false);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
//Create a user if there isn't one
if (realm.where(User.class).count() == 0) {
User user = realm.createObject(User.class);
user.setFirstName("Theo");
user.setLastName("Larsen");
user.setId(UUID.randomUUID().toString());
}
}
});
}
};
handler.postDelayed(r, 1000);
Runnable r1 = new Runnable() {
#Override
public void run() {
final User u = realm.where(User.class).findFirst();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
//Create a task
Task t = realm.createObject(Task.class);
t.setId(UUID.randomUUID().toString());
t.setTitle("Take out recycling");
t.setDescription("Do it every morning");
//set this task to the user.
u.setTask(t);
}
});
Log.d("TASK","Task title: " + u.getTask().getTitle());
}
};
handler.postDelayed(r1, 1000);
}
#Override
public void onDestroy() {
super.onDestroy();
realm.close();
}
}
However,I get this exception.
io.realm.exceptions.RealmException: 'User' has a primary key, use 'createObject(Class<E>, Object)' instead.
at io.realm.Realm.createObjectInternal(Realm.java:820)
at io.realm.Realm.createObject(Realm.java:801)
at theo.testing.realmapp.MainFragment$1$1.execute(MainFragment.java:58)
at io.realm.Realm.executeTransaction(Realm.java:1253)
at theo.testing.realmapp.MainFragment$1.run(MainFragment.java:52)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
I am using that version.
io.realm:realm-gradle-plugin:2.2.1
Any ideas how to fix this exception?
Thanks,
Theo.
Yeah. Do what the exception tells you to do.
Instead of
User user = realm.createObject(User.class);
user.setFirstName("Theo");
user.setLastName("Larsen");
user.setId(UUID.randomUUID().toString());
Do
User user = realm.createObject(User.class, UUID.randomUUID().toString());
user.setFirstName("Theo");
user.setLastName("Larsen");
//user.setId(UUID.randomUUID().toString());
Reason
Primary keys are immutable since Realm 2.0.0, which means you cannot modify them after the object has been created. So pass it at the time of object creation.
Use
User user = realm.createObject(User.class, primaryKeyValue);
add your primary key or generate using UUID.randomUUID().toString()
I've a Fragment where I'm trying to show the ListView using FirebaseRecyclerAdapter which comes in compile 'com.firebaseui:firebase-ui:0.4.2'.
My Fragment code goes like this :
public class HomeFragment extends Fragment {
private RecyclerView services_list;
private DatabaseReference mDatabase;
public HomeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
// Inflate the layout for this fragment
return view;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mDatabase = FirebaseDatabase.getInstance().getReference().child("AllServices");
mDatabase.keepSynced(true);
services_list = (RecyclerView) view.findViewById(R.id.services_list);
services_list.setHasFixedSize(true);
services_list.setLayoutManager(new LinearLayoutManager(getContext()));
}
#Override
public void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Services, ServiceViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Services, ServiceViewHolder>(
Services.class,
R.layout.service_row,
ServiceViewHolder.class,
mDatabase
) {
#Override
protected void populateViewHolder(ServiceViewHolder viewHolder, Services model, final int position) {
viewHolder.setServiceName(model.getName());
viewHolder.setServicePrice(model.getPrice());
viewHolder.setImage(getContext(), model.getImageUrl());
viewHolder.service_name_textview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getContext(), "Clicked on Service Name "+(position+1), Toast.LENGTH_SHORT).show();
}
});
viewHolder.service_price_text_view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getContext(), "Clicked on Service Price "+(position+1), Toast.LENGTH_SHORT).show();
}
});
viewHolder.service_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getContext(), "Clicked on Service Image "+(position+1), Toast.LENGTH_SHORT).show();
}
});
}
};
services_list.setAdapter(firebaseRecyclerAdapter);
}
public static class ServiceViewHolder extends RecyclerView.ViewHolder
{
View mView;
TextView service_name_textview;
TextView service_price_text_view;
ImageView service_image;
public ServiceViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setServiceName(String title)
{
service_name_textview = (TextView) mView.findViewById(R.id.service_name_textview);
service_name_textview.setText(title);
}
public void setServicePrice(String desc)
{
service_price_text_view = (TextView) mView.findViewById(R.id.service_price_text_view);
service_price_text_view.setText(desc);
}
public void setImage(final Context ctx, final String image)
{
service_image = (ImageView) mView.findViewById(R.id.service_image);
//Picasso.with(ctx).load(image).into(post_image);
Picasso.with(ctx).load(image).networkPolicy(NetworkPolicy.OFFLINE).into(service_image, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(ctx).load(image).into(service_image);
}
});
}
}
}
My Services.java code goes like this :
public class Services {
private String Name;
private String ImageUrl;
private String Price;
public Services() {
}
public Services(String name, String imageUrl, String price) {
Name = name;
ImageUrl = imageUrl;
Price = price;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getImageUrl() {
return ImageUrl;
}
public void setImageUrl(String imageUrl) {
ImageUrl = imageUrl;
}
public String getPrice() {
return Price;
}
public void setPrice(String price) {
Price = price;
}
}
There are 21 rows to be displayed into the RecyclerView.
NOTE : once when I installed app for the first time then the data get loaded into the recyclerview (and in the logcat there was images link from where the images were getting downloaded) but after that the data never loaded into the app.
I'm really trying hard to get it sorted but nothing seems to help.
Same problem occurred me. Simply remove the service_list.setHasFixedSize(true).
Sometimes there is an issue in sizing of Recycleview
I also had the same problem that I fixed it with setting
android:layout_width="match_parent"
android:layout_height="match_parent"
just set height and width to match_parent