Data parsing returning a bunch of urls - android

I'm trying to get data using an AsyncLoader. The result I'm getting is only a bunch of links instead of having names of books. This is my code and this is the result. see image here
public class MainActivity extends AppCompatActivity implements
LoaderCallbacks<List<Book>> {
private static final int LOADER_ID=10;
public ArrayAdapter<Book> mAdapter;
private static final String DATA_API_REQUEST="https://www.googleapis.com/books/v1/volumes?q=android&maxResults=10";
private ListView LV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getLoaderManager().initLoader(LOADER_ID,null, MainActivity.this);
}
#NonNull
#Override
public Loader<List<Book>> onCreateLoader(int i, #Nullable Bundle bundle) {
return new BookLoader(this,DATA_API_REQUEST);
}
#Override
public void onLoadFinished(android.content.Loader<List<Book>> loader, List<Book> data) {
LV=(ListView)findViewById(R.id.ListView1);
mAdapter=new ArrayAdapter<Book>(this,android.R.layout.simple_list_item_1,data);
LV.setAdapter(mAdapter);
if (data != null && !data.isEmpty()) {
mAdapter.addAll(data);}
}
#Override
public void onLoaderReset(android.content.Loader<List<Book>> loader) {
mAdapter.clear();
}
Update :
Use
variable.tostring
to the variable that you are setting TextView to. Here you are setting the object directly which the textview cannot convert so instead you can convert the object to String

You are actually printing a whole object try using the element you want to print for instance Book.name.toString() and then set it in the textview you are using in the adapter. furthurmore do paste the adapter code as well to let community understand the issue completely.

as i mentioned in the comment, you need to overwrite the toString() method of your Book class.
Something like this in your Book class:
#Override
public String toString() {
return this.bookName;
}
The output of the default toString method of most objects consists of the class name of the object as well as the object's hashcode, which is usually not what was intended. (From here)

Related

How to set text of TextView with the text selected inside a RecyclerView?

I am trying to implement a "Pin Message" functionality on the chat app I'm developing.
Chat Activity looks like this:
I have a TextView above the chat RecyclerView and would like to set the text of that to the TextView value inside the RecyclerView. I can get the string value of what's inside the RecyclerView by using a PopupMenu (inside its adapter class) by showing it in a Toast for now.
How should I implement this? Thank you!
P.S. I'm still using Java.
I finally found a solution for this one. Link to SO post here -> LINK
First create an interface called PinMessageListener
public interface PinMessageListener {
void onPin(String value);
}
second, implement this interface in your activity or fragment
public class YourActivityOrFragment extends AppCompatActivity implement PinMessageListener {
...
...
...
#Override
public void onPin(String value) {
yourTextView.setText(value);
}
...
}
third, pass this interface in your recycler adapter
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
//this refers to PinMessageManager
YourRecyclerViewAdapter adapter = new YourRecyclerViewAdapter(this);
...
}
your recycler adapter must look like this:
public YourRecyclerViewAdapter extends RecyclerView.Adapter<YourViewHolder> {
private final PinMessageListener pinMessageListener;
public YourRecyclerViewAdapter(PinMessageListener pinMessageListener) {
this.pinMessageListener = pinMessageListener;
}
onCreateViewHolder(...) {
return new YourViewHolder(pinMessageListener);
}
and your viewHolderClass must be look like this:
public YourViewHolder extends RecyclerView.ViewHolder {
private final PinMessageListener pinMessageListener;
public YourViewHolder(View rootView) {
super(rootView);
this.pinMessageListener = pinMessageListener;
}
public void bind(ModelClass model) {
yourTextView.onClickListener((view) -> pinMessageListener.onPin(yourTextView.getText().toString());
}
And that's it.

What happens when you modify class attributes in AsyncTaskLoader

When you try to modify/read a class attribute from the loadInBackground() method. What happens? Does android make a deep copy before passing in the variable?
Do modifications inside loadInBackground() actually change the class attribute values on the exterior context?
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Void>
{
public List<String> some_array = new ArrayList();
public String some_string = "Hello world";
...
#Override
public Loader<Void> onCreateLoader(int id, Bundle args)
{
return new AsyncTaskLoader<Void>(MainActivity.this)
{
#Override
protected void onStartLoading()
{
forceLoad();
}
#Override
public Void loadInBackground()
{
some_array.add("some element");
some_string = "good bye";
}
};
}
#Override
public void onLoadFinished(Loader<Void> loader, Void data)
{
// what are the values of some_array and some_string now?
}
#Override
public void onLoaderReset(Loader<Void> loader)
{
}
}
Okay so I manually tested it and found that in Java, arrays are passed as pointers to the background thread.
Therefore, modifications in the background thread do alter the class variables, but this should be avoided as it is asynchronous and can quickly become unpredictable and chaotic.
My current approach is to store the changes in a temporary, overwritable array and then merge them back in the onLoadFinished method, when we are all back in the same thread.

Getting data from json once and use it in 3 fragment

I am getting the data from JSON using volley, there is 3 Fragment in Activity which I have to populate these fragments with the data that I have received from JSON in MainActivity. I would like to get data from JSON once and use it in Activity and in all those 3 Fragment. I put the received data in a List like this:
List<Display_Activity_Model> videoDetailList;
and I send this list from activity to other fragments using an Interface like:
In activity I have this method:
#Override
public List<Display_Activity_Model> getDataList() {
return videoDetailList;
}
In one of fragments I have:
public interface GetDataInterface {
List<Display_Activity_Model> getDataList();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
sGetDataInterface= (GetDataInterface) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement GetDataInterface Interface");
}
}
#Override
public void onResume() {
super.onResume();
if(sGetDataInterface != null){
dataListFromDispAct = sGetDataInterface.getDataList();
}
}
When I debug the code, I see that the method getDataList in MainActivity is called before the method for fetching json with volley. So all the time I receive empty list.
My question is that: What is the best way to fetch data with volley once and use it in other fragments?
Update1:
#Keita Junichiro:
I defined "update" method in fragment like:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.video_info,container,false);
initComponents(view);
if (dataListFromDispAct != null) {
txt_view_count.setText(dataListFromDispAct.get(0).getView_count());
}
return view;
}
public void update(List<Display_Activity_Model> videoDetailList){
dataListFromDispAct=videoDetailList;
}
and I am calling "update" method in activity after json loaded in "getItemMenuGson" method:
getItemMenuGson(new CallBack() {
#Override
public void onSuccess(List<Display_Activity_Model> itemMenuGsonList) {
videoDetailList=itemMenuGsonList;
new Video_Info().update(videoDetailList);
}
#Override
public void onFail(String msg) {
}
});
The problem is method "onCreateView" in fragment is called before update method. When I declare update method static it is also the same and variable "dataListFromDispAct" is null all the time.
Update2:
Update 3:
#Piyush
I implemented your respond, but it is not working in this problem. I am getting empty list because method onCreateView executing earlier than getItemMenuGson method in Activity. I declared :
SharedApplication mapp = SharedApplication.getInstance();
ArrayList<String> myList = mapp.getArrayListData();
in onActivityCreated in fragment but it is also running before getItemMenuGson method in Activity. The order in which methods are calling:
what should I do? How can I call getItemMenuGson method in Activity to fetch JSON and then load fragment layout to populate those loaded data to the fragment?
Solution: The key for the problem was Static method which runs first:
Define below codes in Fragment:
public class Video_Info extends Fragment {
static TextView txt_view_count;
List<Display_Activity_Model> dataListFromDispAct;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view=inflater.inflate(R.layout.video_info,container,false);
txt_view_count= (TextView) view.findViewById(R.id.txt_view_count);
return view;
}
public static void update(List<Display_Activity_Model> videoDetailList)
{
txt_view_count.setText(videoDetailList.get(0).getView_count());
}
}
In Activity after fetching data from JSON to list call update method:
getItemMenuGson(new CallBack() {
#Override
public void onSuccess(List<Display_Activity_Model> itemMenuGsonList) {
videoDetailList = itemMenuGsonList;
//////////////////
Video_Info.update(videoDetailList);
///////////////////
Uri vidUri = Uri.parse(itemMenuGsonList.get(0).getMedia().getURL());
vidView.setVideoURI(vidUri);
}
In order to send data from activity to fragment after call API, you can create a method update() in fragment to receive data and call fragment.update() in activity when loadData finish().
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//Parse resonse to *videoDetailList*
fragment.update(videoDetailList);
}
}
First make one singletone application class
public class SharedApplication extends Application{
ArrayList<String> arraylist;
public static SharedApplication instance=null;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
public static SharedApplication getInstance()
{
if(instance==null)
{
instance=new SharedApplication();
}
return instance;
}
public void setArrayListData(ArrayList<String> setData)
{
arraylist=setData;
}
public ArrayList<String> getArrayListData()
{
return arraylist;
}
}
Now in your activity initialize your application class using
SharedApplication mApp; // declare global
initialize in onCreate() method
mApp = SharedApplication.getInstance();
Now after parse your data from server set data in arraylist
mApp.setArrayListData(yourArrayList);
Now whenever you want to get data any of fragment you should same initialize your application class in each fragment in which u want to get arraylist.
Like,
SharedApplication mapp = SharedApplication.getInstance();
ArrayList<String> myList = mapp.getArrayListData();
Note : You must add SharedApplication class in your manifest to application tag
Make an interface with a method onDownloadComplete.
public interface DelegateClass {
public static onDownloadComplete(String jsonData);
}
Now fetch data with Volley in Activity and call this method. Implement this interface in all your fragments and override onDownloadComplete. This method will be called when your Activity finishes fetching data. Like
public class YourFragment implements DelegateClass {
...
...
#Override
public static onDownloadComplete(String jsonData){
//do what you want with data
}
...
...
}
Hope it helps

Saving object reference in onSaveInstanceState using Serializable?

I need clarification on how I can save the state of an object that has a reference to another object?
Lets say I have the below class objects that I need to save and restore:
public class ObjectA implements Serializable{
private List<ObjectB> mObjectBList;
}
public clas ObjectB implements Serializable {
// some other members here
private ObjectA mParent;
}
Here are the code to invoke the save and restore in a fragment:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("ObjectA", mObjectA);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
mObjectA = (mObjectA) savedInstanceState.getSerializable("ObjectA");
}
}
Questions:
Will saving mObjectA also save every object in mObjectBList?
Since mObjectB has a reference to its parent ObjectA, will ObjectA be re-instantiated for each ObjectB? Which then in turn will re-instantiate ObjectB, and then it will re-instantiate ObjectA, and so forth, leading to an infinite loop?
How would you solve this problem?
I'm not clear on what happens when an object gets saved as a Serializable, so please help me understand how Android distinguishes when to instantiate a new object and when it will reproduce an actual reference.
Yes. But List is not Serializable. Change List to ArrayList for example.
It works fine. Java serialization works for cyclic references.
Here is similar question.
I think there is no problem.
I did test with following code.
public class MainActivity extends AppCompatActivity {
private ObjectA mObjectA;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
mObjectA = (ObjectA) savedInstanceState.getSerializable("ObjectA");
// check mObjectA == mObjectA.getObjectBList().get(0).getParent();
} else {
mObjectA = new ObjectA();
ArrayList<ObjectB> list = new ArrayList<>();
list.add(createB());
list.add(createB());
list.add(createB());
list.add(createB());
list.add(createB());
mObjectA.setObjectBList(list);
}
}
private ObjectB createB() {
ObjectB objectB = new ObjectB();
objectB.setParent(mObjectA);
return objectB;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("ObjectA", mObjectA);
}
}
public class ObjectA implements Serializable {
private ArrayList<ObjectB> mObjectBList;
public void setObjectBList(ArrayList<ObjectB> objectBList) {
mObjectBList = objectBList;
}
public ArrayList<ObjectB> getObjectBList() {
return mObjectBList;
}
}
public class ObjectB implements Serializable {
// some other members here
private ObjectA mParent;
public void setParent(ObjectA parent) {
mParent = parent;
}
public ObjectA getParent() {
return mParent;
}
}

Give reference to string parameters in outer class method Android

I am calling some function of outer class from my activity and I want to give reference of parameters so that I can get updated value.
I m calling function like this:
My activity:
String var1;
ArrayList<String> var2;
OuterClass outerClass = new Outerclass();
outerClass.someMethod(var1, var2);
My outer Class function:
public void someMethod(String var1,ArrayList<String> var2) {
// after some operations
var1 = "somevale1";
var2 also have some value;
I need to access both of updated value in my activity without any return statement only from reference. But here I am getting error variable accessed from within inner class needs to be declare final but I cannot declare final.
What should I do to give reference just like TextView and EditText?
Try this,
Take a bean class, and put it into var1, var2 and then update in out class method and that updated values reflected into that bean object.
class CustomBean{
String var1;
ArrayList<String> var2;
}
OuterClass outerClass = new Outerclass();
outerClass.someMethod(Bean bean);
public void someMethod(String var1,ArrayList<String> var2) {
// after some operations
bean.var1 = "somevale1";
bean.var2 also have some value;
}
I think you can declare as global variables and make them final.
final String var1;
final Arraylist<String> var2;
You can't update values in such way, because you pass to method just references to where date is stored. What I suggest is change signature of your method, so it returns:
return new Pair<String, ArrayList<String>> (var1, var2);
Krishna's answer is also correct, but I see no real need in such architecture.
Maybe somethink like this. The signature of someMethod was changed.
public class SOActivity extends Activity
{
private String var1;
private ArrayList<String> var2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OuterClass outerClass = new OuterClass();
outerClass.someMethod(this);
android.util.Log.d("SOActivity", "var1=" + var1);
android.util.Log.d("SOActivity", "var2=" + var2.get(0) + var2.get(1));
}
public void setVar1(String var1) {
this.var1 = var1;
}
public void setVar2(ArrayList<String> var2) {
this.var2 = var2;
}
}
public class OuterClass {
public void someMethod(SOActivity soActivity) {
// Some big init for var1 and var2
soActivity.setVar1("somevalue1");
ArrayList<String> al = new ArrayList<String>();
al.add("My");
al.add("solution");
soActivity.setVar2(al);
}
}

Categories

Resources