Issue
I've no idea on how to parse JSON data only once when my application is running. Currently JSON parsing is done on every user interaction like landscape/portrait orientations, page refreshing and page recreation (from child activity) .This makes my application so slow to actually display data every single time. Even app crashes when large number of user interactions like multiple orientation changes are given. Can someone help me how to limit Json parsing not more than once?
JSON Parsing and Saving in Database and ArrayList
public void parseApiData () {
RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
if (response != null) {
if(!books.isEmpty())
{
books.removeAll(books);
dbHandler.removeAll();
}
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
int bookId = obj.getInt("id");
String bookName = obj.getString("title");
String bookDescription = obj.getString("description");
int bookPage = obj.getInt("pageCount");
String bookExcerpt = obj.getString("excerpt");
String bookPublishDate = obj.getString("publishDate");
books.add(new Books(bookId, bookName, bookDescription, bookPage, bookExcerpt, bookPublishDate));
dbHandler.addNewCourse(bookId, bookName, bookDescription, bookPage, bookExcerpt, bookPublishDate);
// books ?
} catch (JSONException e) {
e.printStackTrace();
}
}
//Books[] b=books.toArray(new Books[books.size()]);
//System.out.println(b[184].getmBookName());
//System.out.println(books.get(198).getmBookPage());
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<books.size();j++)
{
Books note=books.get(j);
dbHandler.addNewCourse(note.getmBookId(),note.getmBookName(),note.getmBookDescription(),note.getmBookPage(),note.getmBookExcerpt(),note.getmBookPublishDate());
}
}
});
// books = dbHandler.readCourses();
progressBar.setVisibility(View.GONE);
onConfigurationChanged(getApplicationContext().getResources().getConfiguration());
BookAdapter adapter = new BookAdapter(MainActivity.this, books);
recyclerView.setAdapter(adapter);
} else {
Toast.makeText(MainActivity.this, "Array is empty", Toast.LENGTH_SHORT).show();
}
}
}, new com.android.volley.Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "No Internet Connection", Toast.LENGTH_SHORT).show();
}
});
queue.add(jsonArrayRequest);
};
Parsing in Background to reduce load in main thread
private class AsyncTaskRunner extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... voids) {
try {
if(!run) {
parseApiData();
run=true;
}
}
catch (Exception e){
e.printStackTrace();
}
return null;
}
}
Solution
I assume you having everything in single class (activity) (That's already messy).
This case i believe you have this 2 out side of the function
List<Book> books = new ArrayList<>();
boolean run = false;
For parseApiData you are doing duplicate things, That is what is should be look
public void parseApiData() {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, "url", null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
if (response != null) {
if (!books.isEmpty()) {
books.clear();
dbHandler.removeAll();
}
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
int bookId = obj.getInt("id");
String bookName = obj.getString("title");
String bookDescription = obj.getString("description");
int bookPage = obj.getInt("pageCount");
String bookExcerpt = obj.getString("excerpt");
String bookPublishDate = obj.getString("publishDate");
Book note = new Book( bookId, bookName, bookDescription, bookPage, bookExcerpt, bookPublishDate);
books.add(note);
dbHandler.addNewCourse(note.getmBookId(), note.getmBookName(), note.getmBookDescription(), note.getmBookPage(), note.getmBookExcerpt(), note.getmBookPublishDate());
} catch (JSONException e) {
e.printStackTrace();
}
}
} else {
Toast.makeText(MainActivity.this, "Array is empty", Toast.LENGTH_SHORT).show();
}
}
}, new com.android.volley.Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "No Internet Connection", Toast.LENGTH_SHORT).show();
}
});
Volley.newRequestQueue(this).add(jsonArrayRequest);
}
For AsyncTaskRunner
private class AsyncTaskRunner extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected Void doInBackground(Void... voids) {
if (!run) {
parseApiData();
run = true;
}
return null;
}
@Override
protected void onPostExecute(Void unused) {
super.onPostExecute(unused);
progressBar.setVisibility(View.GONE);
onConfigurationChanged(getApplicationContext().getResources().getConfiguration());
BookAdapter adapter = new BookAdapter(MainActivity.this, books);
recyclerView.setAdapter(adapter);
}
}
Here the repeated :
dbHandler.addNewCourse(bookId, bookName, bookDescription, bookPage, bookExcerpt, bookPublishDate);
With this one:
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<books.size();j++)
{
Books note=books.get(j);
dbHandler.addNewCourse(note.getmBookId(),note.getmBookName(),note.getmBookDescription(),note.getmBookPage(),note.getmBookExcerpt(),note.getmBookPublishDate());
}
}
});
I recommended by changing this too:
onConfigurationChanged(getApplicationContext().getResources().getConfiguration());
BookAdapter adapter = new BookAdapter(MainActivity.this, books);
recyclerView.setAdapter(adapter);
If you request API 3 time it keeping that and rebuild as new again and again
Please consider by create function in your adapter, something like this:
void updateList(List<Book> books){
your_list_in_adapter = books;
notifyDataSetChanged();
}
when onPostExecute you only call that :
youradapter.updateList(books);
This would be much better. Note: AsyncTask, It already deprecated. Please consider change it here.
Answered By - Nrohpos
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.