StrictModeDiskReadViolation only gets resolved with AsyncTask, why? - android

I am using strict mode for android 3.2 and am getting StrictModeDiskReadViolation during onCreate in my Activity.
I tried to moved the code that does an SQL query to:
a new Thread.
a new AsyncTaskLoader.
a new AsynTask.
The problem is only AsyncTask made the Violation dissappear and I'm wondering why the other two methods didn't work?
Here is my code:
AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
Dao<Listino, Integer> dao = DatabaseHelper.getHelper(ListinoActivity.this).getListinoDao();
if (dao.countOf() == 1)
{
long id = dao.queryForAll().get(0).getId();//long non int
final Intent intent = new Intent(ListinoActivity.this, ListinoProdottiActivity.class);
intent.putExtra("listino_id", id);
intent.setAction(Intent.ACTION_MAIN);
ListinoActivity.this.finish();
ListinoActivity.this.startActivity(intent);
}
} catch (SQLException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
MyToast.makeText(ListinoActivity.this, "Errore ottenere i listini", MyToast.LENGTH_SHORT).show();
}
});
e.printStackTrace();
}
return null;
}
};
asyncTask.execute();
AsyncTaskLoader async = new AsyncTaskLoader(this) {
#Override
public Object loadInBackground() {
//do stuff, violation still here
return null;
}
};
async.loadInBackground();
Thread t = new Thread() {
#Override
public void run() {
super.run();
//do stuff, violation still here
}
};
t.run();

You did not fork a Thread. To fork a Thread, you call start(). You called run(), which simply ran your run() method on the current thread.
And you did not come even close to using the Loader framework properly. The code you have there not only suffers from the same flaw as what you did with your Thread, but that is not how you use a Loader.

Related

Asynchronous task is executed 2 times because of the poor quality of the internet-

I have an asynchronous task in Android Studio, to send and receive data from a server as follows.
private class myTask extends AsyncTask<Void, Void, Integer> {
Exception excepccion;
protected void onPreExecute() {
super.onPreExecute();
Mensaje.mensajeConectandoseSicoy(actMetodoPago,getString(R.string.msg_conexion_sicoy));
}
#Override
protected Integer doInBackground(Void... params) {
try {
return new Servidor().guardarObtnerInfoServidorSicoy(ACCION_PAGAR_PEDIDO);
} catch (Exception e2) {
excepccion = e2;
return -1;
}
}
#Override
protected void onPostExecute(Integer respuesta) {
Mensaje.detenerMensajeConectandoseSicoy();
...
}
Where:
public static void mensajeConectandoseSicoy(Context context, String mensaje){
pd = new ProgressDialog(context);
pd.setMessage(mensaje);
pd.setCancelable(false);
Handler pdCanceller = new Handler();
pd.show();
}
public static void detenerMensajeConectandoseSicoy(){
if (pd.isShowing()){
pd.dismiss();
}
}
This process works very well until a user reported problems and discovered that their internet is of very poor quality.
When the task is running onPostExecute, that is, when the server has already responded, it is again executed onPreExecute, and this triggers a series of errors.
I solved it by putting a Boolean type flag variable, to avoid the problem.
My question is:
Is there a way to do that control in a better way?

doInBackground is not getting called sometimes Android

In my application, there are multiple asynctasks. Please let me know why doInBackground of an asynctask sometimes does not getting called. Its onPreExecute method gets called. Is there any issue because of multiple asynctasks or something else?
/* ASync class for test table */
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
If your project has multiple asynctasks you must check that there is a limit of asynctasks that can be executed. When you create a new AsyncTask it will be added on a Pool and will be execute only when is possible.
Check this answer:
Multitasking on android
And the docs: ThreadPoolExecutor
Here is an example on how properly handle multiple AsyncTasks AsyncTaskManager
OnPreExecute() gets called on the UI thread and doInBackground() is called on the background thread.
There is one dedicated background thread for the async task. This behaviour can be changed if you want to.
http://android-er.blogspot.in/2014/04/run-multi-asynctask-as-same-time.html
Now, say you have multiple instances of async task and I'm assuming you are calling execute() to run the async tasks. This will trigger all the preExecute immediately since UI thread is free but for the doInBackground it will triggered one by one. Hence it may take some time for the next async task to start.
doInBackground should run on a loop using a Boolean to check before execution. Before your Task is being executed, set a global boolean (may be true/false) depends on which you prefer and values add on thread should call runOnUiThread.
startExect = true;
new TestAsynch().execute();
then change this
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
to this
public class TestAsynch extends AsyncTask<String, Void, String> {
String result1 = null;
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
result1=API_Manager.getInstance().sendTestData(userName);
while (startExecute) {
Thread exe = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5);
}
catch( Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
if(result1 != null) {
// save in db
}
}
});
}
}); exe.start();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}

Using view elements inside thread

I'm trying to do a simple HTTP request in Android. It has to be in separate theread. But how can I operate on the view controls inside the thread?
Here's what I have now:
public void saveData(final View v)
{
Button btn = (Button) v.findViewById(R.id.button);
btn.setText("Saving...");
new Thread() {
public void run()
{
HttpURLConnection connection = null;
try {
URL myUrl = new URL("http://example.com");
connection = (HttpURLConnection)myUrl.openConnection();
InputStream inputStream = connection.getInputStream();
final String fResponse = IOUtils.toString(inputStream);
}
catch (MalformedURLException ex) {
Log.e("aaa", "Invalid URL", ex);
}
catch (IOException ex) {
Log.e("aaa", "IO Exception", ex);
}
finally {
if (connection != null) {
connection.disconnect();
}
}
// How can I access v and btn here?
// btn.getText("Saved, thanks.");
// btn.setText("Saved, thanks.");
}
}.start();
}
To elaborate what I'm trying to achieve:
I have a text box and a button. Once the button is clicked, I want to get the text from text box, use in the URL, wich returns a value, then update the button text with this value.
Here's an example on how you could do it.
public class YourClass extends Activity {
private Button myButton;
//create an handler
private final Handler myHandler = new Handler();
final Runnable updateRunnable = new Runnable() {
public void run() {
//call the activity method that updates the UI
updateUI();
}
};
private void updateUI()
{
// ... update the UI
}
private void doSomeHardWork()
{
//update the UI using the handler and the runnable
myHandler.post(updateRunnable);
}
private OnClickListener buttonListener = new OnClickListener() {
public void onClick(View v) {
new Thread(new Runnable() {
doSomeHardWork();
}).start();
}
};
}
As you can see, you need to update the UI with yet another Runnable object. This is one way of doing it.
Another option is via the runOnUiThread function
runOnUiThread(new Runnable()
{
#Override
public void run() {
updateActivity();
}
});
If you try to access your Views directly from another thread like that, you will get an exception because all UI operations must be performed on the main thread.
One method that the Android SDK provides for performing background tasks that need to update the UI is the AsyncTask.
The onPostExecute() method of an AsyncTask is called after doInBackground() returns, and is run on the UI thread.
Your AsyncTask might look something like this:
public class MyBackgroundTask extends AsyncTask<URL, Void, String> {
protected String doInBackground(URL... urls) {
URL myUrl = new URL("http://example.com");
connection = (HttpURLConnection)myUrl.openConnection();
InputStream inputStream = connection.getInputStream();
return IOUtils.toString(inputStream);
}
protected void onPostExecute(String result) {
// Call back to your Activity with the result here
}
}

Delivering AsyncTask result to an other activty

I am trying to retrieve my data from Parse.com during splash screen.
I'm making the query in the DoInBackground method and add all objects retrieved in an object vector (which is in an other class).
when moving to the MainActivty all data get loss.
Here's my code:
private class loadDataTask extends AsyncTask<Void, Void, Vector<PartyObj>>{
#Override
protected Vector<PartyObj> doInBackground(Void... params)
{
ParseQuery query = new ParseQuery("partyObj");
query.whereExists("Name");
query.findInBackground(new FindCallback() {
#Override
public void done(List<ParseObject> mNameList, ParseException e) {
if (e == null) {
adapter.partyVector = new Vector<PartyObj>();
for(int i=0; i<mNameList.size(); i++){
PartyObject party = new PartyObject();
party.setIndex(i);
party.setmName(mNameList.get(i).getString("Name").toString());
adapter.partyVector.add(party);
}
}else {
Log.d("mNameList", "Error: " + e.getMessage());
}
}
});
return adpater.partyVector;
}
#Override
protected void onPostExecute(Vector<PartyObj> result) {
progressDialog.dismiss();
setContentView(R.layout.activity_main_menu);
}
}
It seems like you're using the AsyncTask all wrong. query.findInBackground() is as far as I can tell an asynchronous call so you're essentially wrapping one async call in another. The problem with this is that code execution continues immediately after query.findInBackground(), thus ending the doInBackground() method. Since you move to the main activity immediately when the async task is finished it may be that query.findInBackground() hasn't finished yet (thus resulting in an empty/partial list).
Are you really sure you need to wrap everything in an async call? Does either of
ParseQuery query = new ParseQuery("partyObj");
query.whereExists("Name");
take time to execute or is the bulk of the work already in the async findInBackground() call? If so, I'd say skip the AsyncTask and do the view transition in the done() method of the FindCallback.
UPDATE: I've read up on ParseQuery and it clearly says:
Using the callback methods is usually preferred because the network
operation will not block the calling thread. However, in some cases it
may be easier to use the find, get or count calls, which do block the
calling thread. For example, if your application has already spawned a
background task to perform work, that background task could use the
blocking calls and avoid the code complexity of callbacks.
And in findInBackground() it clearly states that:
Retrieves a list of ParseObjects that satisfy this query from the
server in a background thread. This is preferable to using find(),
unless your code is already running in a background thread.
Since you are already wrapping everything in an AsyncTask you should either skip the async task completely since findInBackground( is already running in a background thread or switch to the blocking find() method.
Example without AsyncTask but using async findInBackground():
ParseQuery query = new ParseQuery("partyObj");
query.whereExists("Name");
query.findInBackground(new FindCallback() {
#Override
public void done(List<ParseObject> mNameList, ParseException e) {
if (e == null) {
adapter.partyVector = new Vector<PartyObj>();
for(int i=0; i<mNameList.size(); i++){
PartyObject party = new PartyObject();
party.setIndex(i);
party.setmName(mNameList.get(i).getString("Name").toString());
adapter.partyVector.add(party);
}
progressDialog.dismiss();
setContentView(R.layout.activity_main_menu);
}
else {
Log.d("mNameList", "Error: " + e.getMessage());
}
}
});
Example with AsyncTask and blocking find()
private class loadDataTask extends AsyncTask<Void, Void, Vector<PartyObj>>{
#Override
protected Vector<PartyObj> doInBackground(Void... params)
{
ParseQuery query = new ParseQuery("partyObj");
query.whereExists("Name");
Vector<PartyObject> v = new Vector<PartyObject();
try {
List<ParseObject> queryResult = query.find();
for(ParseObject po : queryResult) {
PartyObject party = new PartyObject();
party.setIndex(partyVector.size());
party.setmName(po.getString("Name").toString());
v.add(party);
}
}
catch(ParseException e) {
Log.d("mNameList", "Error: " + e.getMessage());
}
return v;
}
#Override
protected void onPostExecute(Vector<PartyObj> result) {
adapter.partyVector.addAll(result);
progressDialog.dismiss();
setContentView(R.layout.activity_main_menu);
}
}
I have implemented similar async class for getting parse server data
private class Getneworders_list extends AsyncTask<Void, Void, List<ParseObject>> {
ArrayList<HashMap<String, String>> neworders_hashmap;
#Override
protected void onPreExecute() {
super.onPreExecute();
neworders_recyclerView.getRecycledViewPool().clear();
}
#Override
protected List<ParseObject> doInBackground(Void... params) {
// Create the array
try {
ParseQuery<ParseObject> query = ParseQuery.getQuery("Orders");
ParseObject obj = ParseObject.createWithoutData("ShopLocations", idd);
query.whereEqualTo("shop", obj);
query.whereEqualTo("orderStatus",0);
query.setCachePolicy(ParseQuery.CachePolicy.IGNORE_CACHE);
query.orderByDescending("updatedAt");
object11 = query.find();
} catch (ParseException e) {
Log.d("Error", e.getMessage());
e.printStackTrace();
}
return object11;
}
#Override
protected void onPostExecute(List<ParseObject> result) {
neworders_hashmap = new ArrayList<HashMap<String, String>>();
if(result != null) {
if (result.size() > 0) {
chec(result.size());
m_Runnable.run();
}
}
}
}
use full for some one

How to close parent thread on Android

I would like to do step by step upload date to web service.
My code:
private Thread WebServiceThread;
public void onCreate(Bundle savedInstanceState) {
//...
WebServiceThread = new WebService();
WebServiceThread.start();
}
private class WebService extends Thread {
public void run() {
try {
new WebServiceUpload().execute("");
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT)
.show();
}
}
}
private class WebServiceUpload extends AsyncTask<String, Void, String> {
protected String doInBackground(String... data) {
// upload part
}
protected void onPostExecute(String result) {
//...
WebServiceThread = new WebService();
WebServiceThread.start();
//<Tab>__what to do here__</Tab>
//...
}
}
Now can run, but cause the device slow.
Please tell me how to close parent thread or restart parent thread way to solve this problem. (or other practice to same target.)
You don't have to chain threads like that. Just create a single AsyncTask extension that uploads the data step by step in doInBackground. If you want to publish progress reports, you can do that by calling publishProgress.
Your method of creating a WebServiceUpload from a worker thread is really bizarre and will most likely not work. AsyncTask is designed to be started from the UI thread. Just call your new WebServiceUpload().execute() from the main thread when you want to start the upload steps.
In your onPostExecute check if thread is running then force it to stop.
protected void onPostExecute(String result) {
//...
**if (WebServiceThread.isAlive())
WebServiceThread.stop();**
WebServiceThread = new WebService();
WebServiceThread.start();
//<Tab>__what to do here__</Tab>
//...
}

Categories

Resources