Reputation: 311
I have an activity that calls JSON data from a foreign database. Below is my ideal case for my app:
What actually happens:
How do I force Android to wait until database insertion is completed before starting the next activity?
EDIT
My doInBackground
looks as follows:
@Override protected String doInBackground(String... params) { StringRequest strReq = new StringRequest(Request.Method.GET, str, new Response.Listener<String>() { @Override public void onResponse(String response) { try { JSONObject jObj = new JSONObject(response); boolean error = jObj.getBoolean("error"); // Check for error node in json if (!error) { JSONArray jObjInside = jObj.getJSONArray("service_prov_services"); for (int i = 0; i < jObjInside.length(); i++) { // Now store the user in SQLite try { // JSONObject user = jObj.getJSONObject("user"); String service_prov_type = jObj.getString("service_prov_type"); String service_prov_name = jObj.getString("service_prov_name"); String addr_street = jObj.getString("addr_street"); String addr_num = jObj.getString("addr_number"); String addr_plz = jObj.getString("addr_plz"); String addr_city = jObj.getString("addr_city"); JSONObject elem = jObjInside.getJSONObject(i); if(elem != null){ String service_id = elem.getString("service_id"); String service_type = elem.getString("service_type"); String service_measure = elem.getString("service_measure"); // Inserting row in userServiceProvServices table db.addUserServiceProvServices(service_id, service_prov_type, service_prov_name, addr_street, addr_num, addr_plz, addr_city, service_type, service_measure); Log.d("post_url for service", addr_plz ); } } catch (JSONException e) { // JSON error e.printStackTrace(); Toast.makeText(getActivity().getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show(); } } } else { // Error in login. Get the error message String errorMsg = jObj.getString("error_msg"); Toast.makeText(getActivity().getApplicationContext(), errorMsg, Toast.LENGTH_LONG).show(); } } catch (JSONException e) { // JSON error e.printStackTrace(); Toast.makeText(getActivity().getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "Login Error: " + error.getMessage()); Toast.makeText(getActivity().getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show(); } }); Log.d("test string to appcntr",strReq.toString()); // Adding request to request queue AppController.getInstance().addToRequestQueue(strReq, tag_string_req); return params[0]; }
onPostExecute
looks as follows:
@Override protected void onPostExecute(String Result) { //super.onPostExecute(Result); pdLoading.dismiss(); //this method will be running on UI thread Log.d(TAG, "Stamp: " + Result); Bundle args = new Bundle(); args.putString("stampID", Result); ProviderServiceListFragment frag = new ProviderServiceListFragment(); frag.setArguments(args); FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, frag) .commit(); }
With the way I am doing it now, my next Fragment is already called, although the data has not finished being entered into the database. This means the ListArray in the follwoing Fragment is empty because of the missing database data.
Upvotes: 3
Views: 7165
Reputation: 374
I worked on this for a month and finally figured it out for myself (stupid nube I am..) So here is a piece of code inserting a record to sqlite.
On the chosen event ("onClick actionbutton1") a new AsyncTask is created with doInBackground, onPreExecute and onPostExecute.
onPreExecute will setMessage() and show() the progressDialog which will start spinning
onPostExecute will handle the new/next Activity
READ BELOW FOR doInBackground!!
actionButton1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final ProgressDialog progressDialog = new ProgressDialog(AddUpdateEvf.this);
new AsyncTask<Void, Void, Boolean>() {
protected Boolean doInBackground(Void... params) {
doOneThing();
return null;
}
@Override
protected void onPreExecute() {
progressDialog.setMessage("Processing...");
progressDialog.show();
}
protected void onPostExecute(Boolean result) {
evaluationFormOps.close();
progressDialog.dismiss();
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(AddUpdateEvf.this);
alertDialogBuilder.setMessage("Added to Database...")
.setCancelable(false)
.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
i = new Intent(AddUpdateEvf.this, ViewProduct.class);
i.putExtra(EXTRA_ADD_UPDATE, "View");
i.putExtra(EXTRA_PRODUCT_ID, hiddenTextId.getText().toString());
i.putExtra(EXTRA_PRODUCT_NO, productNo_tv.toString());
startActivity(i);
dialog.dismiss();
finish();
}
});
AlertDialog alert = alertDialogBuilder.create();
alert.show();
}
private void doOneThing() {
makeDbRequest();
do {
evfId = newEvf.getEvfId();
}
while (evfId<1);
}
}.execute();
}
});
Note this snippet in the above code called in doInBackground():
private void doOneThing() {
makeDbRequest();
do {
evfId = newEvf.getEvfId();
}
while (evfId<1);
}
Note: The makeDbRequest() handles the insert to sqlite by setting the values and then passing it to another class which handles the cursor and puts the values etc.
Heres a small snippet of relevant code in that class (which you should already have mastered...):
public Evf addEvf(Evf evf, String dBsuccess){
ContentValues values = new ContentValues();
values.put(TableHelper.PRODUCT_IDE,evf.getPRODUCTId());
values.put(TableHelper.CSCORE,evf.getcScore());
values.put(TableHelper.FSCORE,evf.getfScore());
values.put(TableHelper.TSCORE,evf.gettScore());
values.put(TableHelper.WEIGHT,evf.getWeight());
values.put(TableHelper.TEMP,evf.getTemp());
values.put(TableHelper.STATUS,evf.getStatus());
values.put(TableHelper.TIMESTAMP, String.valueOf(evf.getTimeStamp()));
values.put(TableHelper.LOADED, dBsuccess);
long insertid = database.insert(TableHelper.TABLE_EVFS,null,values);
evf.setEvfId((int) insertid);
return evf;
}
So above you can see the Id of, in my case evaluationform(Evf), being set to the insert id. This happens after the insert and you can set any value in your object class (the one with getters and setters...Evf())
Finally, use the do...while statement above to "listen" for the value being set in the object class
This can obviously only happen if the insert was finished and the onPosteExecute takes care of the rest
Hope it helps, crit is welcome, PEACHES!!
Upvotes: 2
Reputation: 629
The StringRequest is an Asynchronous request, so upon the executing the those lines onPostExecute will called immediately, so there is no guarantee that the sql update will complete before the next activity is launched.
Call the nextActivity at the end of the onResponse callback method of the StringRequest which way you can guarantee to insert the data to db first and then call the nextActivity.
private void makeJsonRequest(String str) {
StringRequest strReq = new StringRequest(Request.Method.GET,
str, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
JSONArray jObjInside = jObj.getJSONArray("service_prov_services");
for (int i = 0; i < jObjInside.length(); i++) {
// Now store the user in SQLite
try {
// JSONObject user = jObj.getJSONObject("user");
String service_prov_type = jObj.getString("service_prov_type");
String service_prov_name = jObj.getString("service_prov_name");
String addr_street = jObj.getString("addr_street");
String addr_num = jObj.getString("addr_number");
String addr_plz = jObj.getString("addr_plz");
String addr_city = jObj.getString("addr_city");
JSONObject elem = jObjInside.getJSONObject(i);
if (elem != null) {
String service_id = elem.getString("service_id");
String service_type = elem.getString("service_type");
String service_measure = elem.getString("service_measure");
// Inserting row in userServiceProvServices table
db.addUserServiceProvServices(service_id, service_prov_type,
service_prov_name, addr_street, addr_num, addr_plz, addr_city, service_type, service_measure);
Log.d("post_url for service", addr_plz);
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
goNextActivity();
} else {
// Error in login. Get the error message
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getActivity().getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Login Error: " + error.getMessage());
Toast.makeText(getActivity().getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
}
});
Log.d("test string to appcntr", strReq.toString());
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
private void goNextActivity(){
//this method will be running on UI thread
ProviderServiceListFragment frag = new ProviderServiceListFragment();
frag.setArguments(args);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame,
frag)
.commit();
}
Upvotes: 0
Reputation: 5084
Use AsyncTask to process the Database insertion process & then use the onPostExecute method to move away from the current activity.
private class ProcessDatabase extends AsyncTask<String, String, String> {
String sampleData;
@Override
protected String doInBackground(String... params) {
//Call your Database Insert method here.
//In this example, I am inserting sampleData to the DB
return null;
}
@Override
protected void onPostExecute(String result) {
//This gets triggered when the process is complete
}
}
You can start the AsyncTask by adding the following code in your onCreate or where ever you want to start the DB Insertion process:
//in this case I am just passing a string, You can create your own
//custom class & send that as well
ProcessDatabase.execute(myData);
Refer this link for more information. Good luck!
Upvotes: 0