I'm using Room as the database for the app. I`m fetching data from the server using Retrofit. the scenario is i have a class called Photo and annotated with Entity to be used by room, and im using this class to map the response of the API using retroft. i need to create two tables using the same class for example: latest_photos table and popular_photos table. How can i achieve this.
I don`t want to create a new class and make it extends from the other
I have an idea of using a single table through inserting a new column
that indicates weather the photo is popular or latest but i dont know
how to implement it efficientlly.
public void insertPhotos(final List photos) {
ioExecutor.execute(new Runnable() {
#Override
public void run() {
photoDao.bulkInsert(updateList(photos));
}
});
}
here im inserting list of photos (consists of 20 photo object). how can i add a new field to every photo object.
i`ve tried to use for loop but it takes noticeable time as i dont receive only 20 items but im paginating through the web server.
is there any way to add a new value to retrofit response and mapping
it to the Photo class
Ive solved the problem,now im dealing with only one table. i`ve inserted a new column that indicates weather the photo is popular or latest but the problem is the server is not returning any useful data to fill this column. so the only solution is to modify the json response before mapping to to my entity. so making retrofit call returning type to be ResponseBody to return json string itself and not to map it, so i can add a property to json response then i map it with the newly add property.
private void processData(Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
JSONObject jsonObject = new JSONObject(response.body().string());
JSONArray hits = jsonObject.getJSONArray("hits");
List<Photo> photos = new ArrayList<>();
for (int i = 0; i < hits.length(); i++) {
JSONObject photoJSONObject = hits.getJSONObject(i);
photoJSONObject.put("order", order); // add new property
String json = photoJSONObject.toString();
Gson gson = new Gson();
Photo photo = gson.fromJson(json, Photo.class);
photos.add(photo);
}
Related
I have a simple listview, which is loading data from a really huge JSON.
Currently I have it done like the example below - so I am pulling ALL the data from JSON. This is only an example, I have much more data there to assign to actorList:
protected Boolean doInBackground(String... args) {
HttpHandler sh = new HttpHandler();
String url = "androidnews.json";
String jsonStr = sh.makeServiceCall(url);
if (jsonStr != null) {
try {JSONObject jsonObj = new JSONObject(jsonStr);
JSONArray actors = jsonObj.getJSONArray("result");
for (int i = 0; i < actors.length(); i++) {
JSONObject c = actors.getJSONObject(i);
Actors actor = new Actors();
actor.setNazov(c.getString("name"));
actor.setPerex(c.getString("desc"));
actor.setPlace(c.getString("place"));
actor.setGps1(c.getString("gps1"));
actor.setGps2(c.getString("gps2"));
actor.setContact(c.getString("contact"));
actor.setinfo(c.getString("info"));
//and much more data from JSON
actorsList.add(actor);
}
However, it is working fine, but I think it is loading all the data for no reason.
Because in the listview I will use only title and description and all the other data will be passed only to the onclick activity of each item.
So I thought I will pass to onclick activity only the item's name, and in the other activity I will call a PHP file, which according this name as parameter will generate JSON with all other data, which will only be used in the other activity.
Am I doing this a better way?
I really don't think it's usefull to load all the unnecessary data when I will use only some of them.
So - actually there will be 2 jsons, one smaller for the listview and one for the details, but the second one will be called ONLY when user clicks some item in listview, so not everytime with the listview.
I'm switching an Android project to using Couchbase Lite, and I'm confused with ways for fetching the data from the database.
I have a document, which contains only one property:
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("data_key", json);
Document document = database.getDocument("data_doc_id");
document.putProperties(properties);
The next my step is getting the stored data from the database. I found two ways:
The first approach is reading the document
Document doc = database.getDocument("data_doc_id");
String json = (String) doc.getProperty("data_key");
The second one is querying
View view = database.getView("data_json");
view.setMap(new Mapper() {
#Override
public void map(Map<String, Object> document, Emitter emitter) {
if ("data_doc_id".equals(document.get("_id")) {
String json = (String) doc.getProperty("data_key");
emitter.emit("data_key", json);
}
}
}, "1.0");
QueryEnumerator queryEnumerator = view.createQuery().run();
String dataJson = "";
for (QueryRow queryRow : run) {
if ("data_key".equals(queryRow.getKey()) {
json = (String) queryRow.getValue();
}
}
Is it okay to use the first approach to get the stored JSON?
For what cases the second approach should be used? It has far more code than the first one, maybe it has something to do with caching or/and speed/performance? What are the pros and cons of this approach?
The first approach is retrieving the document directly. This is the fastest way to do it.
With databases, though, often you want to retrieve documents based on some feature of the data. To do this you want the ability to create queries about the data. That's what the second approach is for.
Its the data for a quiz, which include "id" as question ID and "test_id" as a quiz ID. I need to fetch all the question(no. of question may differ) and options with correct answer and need to populate it in a recyclerview.
[
{
"id":"13",
"test_id":"1",
"question":"find out relationship with the third word.",
"options":"[\"speed\",\"hiking\",\"needle\",\"direction\"]",
"correct_answer":"3",
"create_date":"2016-10-27 07:37:39",
"update_date":null
},
{
"id":"14",
"test_id":"1",
"question":"find out which of the answer choices completes the same relationship with the third word.",
"options":"[\"not\",\"set\",\"get\",\"pet\"]",
"correct_answer":"3",
"create_date":"2016-10-28 07:37:39",
"update_date":null
},
{
"id":"15",
"test_id":"1",
"question":"the same relationship with the third word.",
"options":"[\"jet\",\"read\",\"nor\",\"sour\"]",
"correct_answer":"3",
"create_date":"2016-10-28 10:37:39",
"update_date":null
},
{
"id":"16",
"test_id":"1",
"question":"A good way to figure out the relationship ",
"options":"[\"trekking\",\"hiking\",\"seed\",\"turn\"]",
"correct_answer":"3",
"create_date":"2016-10-28 18:37:39",
"update_date":null
}
]
I have used this code:
String res = new QuestionRequest(getActivity().getApplicationContext(), "level_question").execute(test_id).get();
JSONArray result = new JSONArray(res);
List<DataQuestion> data=new ArrayList<>();
for(int i=0;i<result.length();i++){
JSONObject json_data = result.getJSONObject(i);
DataQuestion rowdata = new DataQuestion();
rowdata.id= json_data.getString("id");
rowdata.test_id= json_data.getString("test_id");
rowdata.question= json_data.getString("question");
rowdata.answer_choices= json_data.getString("answer_choices");
rowdata.correct_answer= json_data.getString("correct_answer");
data.add(rowdata);
}
I have stored it in arraylist. Now how should send it another fragment. I tried to send data using Bundle but don't know how to send arraylist.
where:
DataQuestion.java is
public class DataQuestion {
public String id;
public String test_id;
public String question;
public String answer_choices;
public String correct_answer;
}
I suggest you to use the library Retrofit (https://square.github.io/retrofit/) to call API request and serialize the response. In your case you will create a class with many field (id, test_id, question, options,...).
And then you create an adapter for your recyclerview which accept your model class. And finally you display your item with cardview for example.
Its better if you post what you have tried to parse this json. Parsing json is very easy in android you just have to create this a JSONArray or JSONObject from the data you have. In your case its a JSONArray.
Later you can create your models which will contain the json data , you can pass the model to a adapter and user that adapter in a recyclerview or list.
You can use Volley to fetch the data and create a JSONObject to parse the Response into a list of Questions (using model) and then pass that list to an adapter where you can set the question in your list item in RecyclerView/ListView.
Okay so, I created an app that retrieves data from my server using JSON. Now I want to store the retrieved data on my phone's local storage/db. How do I do it? I am new in android programming.
This is the JSON that I receive from the server
{"messages":[{"id":"44","issender":0,"content":"CAT1DOG","date":"Jan 01, 1970 07:30 AM","sender":"Administrator","receiver":"User"},{"id":"57","issender":0,"content":"ttt","date":"Jun 30, 2016 03:43 PM","sender":"Administrator","receiver":"User"},{"id":"58","issender":0,"content":"s","date":"Jun 30, 2016 03:43 PM","sender":"Administrator","receiver":"User"},{"id":"82","issender":0,"content":"yeuwu","date":"Jun 30, 2016 04:59 PM","sender":"Administrator","receiver":"User"}],"success":1}
and this is my code to parse JSON
for(int i = 0; i < messages.length(); i++){
JSONObject o = messages.getJSONObject(i);
String msgid = o.getString("id");
String message = o.getString("content");
String date = o.getString("date");
String sender = o.getString("sender");
String receiver = o.getString("receiver");
String issender = o.getString("issender");
// TEMP HASHMAP FOR USER
HashMap<String, String> msgList = new HashMap<String, String>();
// ADDING EACH CHILD NOTE TO HASHMAP => VALUE
msgList.put("id", uid);
msgList.put("message", message);
msgList.put("date", date);
msgList.put("name", sender);
msgList.put("receivername", receiver);
// ADDING USER TO MSGLIST
ListOfMsg.add(msgList);
}
Thanks in advance for those who will answers. will appreciate it.
First I need to tell you that this is not the easy way out but for sure it is the correct one.
Next create a new class named Message
public class Message{
public String issender;
}
When you receive the json :
List<Message> messages= new ArrayList<>();
Gson gson = new Gson();
Message m= gson.fromJson(json.toString(),Message.class);
messages.add(m);
Please be careful that the items in the class should have the name as the items in the json you are trying to receive
Now we are done with this part:
Let us add the library for caching:
Follow this tutorial and if you need help get back to me:
https://guides.codepath.com/android/activeandroid-guide
or you could do the caching using sql old fashioned way
You can do this in two ways:
Use the new extension for json in sqite. The information you might need is available on this page https://www.sqlite.org/json1.html . Still I would suggest to do a little bit more of research on this, as it is new and I have not used it yet.
You can convert your json to string and insert it to the database.
String jsontostring = jsonObject.toString();
I'm writing an Android application which will occasionally need to download a json string of around 1MB and containing around 1000 elements, and parse each of these into an SQLite database, which I use to populate a ListActivity.
Even though the downloading and parsing isn't something that needs to be done on every interaction with the app (only on first run or when the user chooses to refresh the data), I'm still concerned that the parsing part is taking too long, at around two to three minutes - it seems like an eternity in phone app terms!
I'm currently using Gson to parse each json object into a custom object that I've defined, and then using an SQLiteOpenHelper to enter it into the database.
My question is - is there a faster way of implementing this? Would it be noticeably faster to interact with the json directly, without using Gson? Or am I doing something stupid in the code below that's slowing things down?
Here's the method I'm using in my AsyncTask to parse the json to SQLite:
protected Boolean doInBackground(Integer... bType) {
InputStream source = getJsonInputStream(bTypeString);
VegDataHandler db = new VegDataHandler(mainActivity, bTypeString);
Gson gson = new Gson();
Reader reader = new InputStreamReader(source);
JsonParser jParser = new JsonParser();
JsonArray jArray = jParser.parse(reader).getAsJsonArray();
aLength = jArray.size();
mCurrProgress = 1;
publishProgress(mCurrProgress, 0, aLength);
/* Each array element is of the form { company: {...} } */
int i = 0;
mCurrProgress = 2;
for (JsonElement obj : jArray) {
Company c = gson.fromJson(obj.getAsJsonObject().getAsJsonObject("company"), Company.class);
db.addCompany(c);
i++;
publishProgress(mCurrProgress, i);
}
}
This is the addCompany method from my VegDataHandler class, which extends SQLiteOpenHelper:
public void addCompany(Company c) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_ID, c.getCompanyId());
values.put(KEY_NAME, c.getCompanyName());
values.put(KEY_RYG, c.getCompanyRedYellowGreen());
values.put(KEY_COUNTRY, c.getCompanyCountry());
values.put(KEY_URL, c.getCompanyUrl());
values.put(KEY_NOTES, c.getCompanyNotes());
values.put(KEY_EMAIL, c.getCompanyEmail());
db.insertWithOnConflict(TABLE_COMPANY, null, values, SQLiteDatabase.CONFLICT_REPLACE);
db.close();
}
This is the class that holds each json element before adding to the SQLite (I've omitted the getters and setters for brevity).
public class Company {
public Company() {
}
#SerializedName("id")
public int companyId;
#SerializedName("company_name")
public String companyName;
#SerializedName("red_yellow_green")
public String companyRedYellowGreen;
#SerializedName("country")
public String companyCountry;
#SerializedName("url")
public String companyUrl;
#SerializedName("notes")
public String companyNotes;
#SerializedName("email")
public String companyEmail;
}
Thanks in advance for any replies.
First you need to determine the portion(s) of the process that are eating up the most time. From your comment above it sounds like the JSON parsing is the culprit.
If JSON parsing is the issue:
Research and consider a faster JSON parser. Perhaps something like json-smart.
If SQLite/DB bulk inserts are the issue:
See my answer here
General tips:
Recycle objects as much as possible (keep new to a minimum)
Always use transactions in DB bulk inserts at the very least
Don't open/close the database. Do this once at the start/finish of your processing
Use pre-compiled statements!