I have the created the following Async function-
private class CustomAsyncUtil extends AsyncTask<String, Void, String> {
private void CreateDocument(){
try
{
//doing some work
}
catch (Exception ex)
{
String exp = ex.getMessage();
}
}
#Override
protected String doInBackground(String[] params) {
if(android.os.Debug.isDebuggerConnected())
android.os.Debug.waitForDebugger();
CustomAsyncUtil objUtil = new CustomAsyncUtil();
objUtil.CreateDocument();
return "some message";
}
#Override
protected void onPostExecute(String message) {
//process message
}
}
I am calling the function like this-
CustomAsyncUtil objUtil = new CustomAsyncUtil();
objUtil.execute();
To be debug I have added if(android.os.Debug.isDebuggerConnected()) inside doInBackground() but I don't get a break point inside CreateDocument(). Any idea what I am doing wrong?
When you call
CustomAsyncUtil objUtil = new CustomAsyncUtil();
objUtil.CreateDocument();
you are calling CreateDocument() on a different async task object. If you want to call this helper method inside the same async task, then just call it directly:
CreateDocument();
An AsyncTask has a number of lifecycle methods, the most basic of which include:
onPreExecute()
doInBackground()
onProgressUpdate()
onPostExecute()
In general, all the work you do in an async task will originate in one of these entry points, then possibly including helper methods you call from the lifecycle methods.
Related
I use async task to get data from my database.
i have :
public class BackgroundDatabaseTask extends AsyncTask<String, Void, String> {
String jsonData;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... values) {
String jsonData = Driver.returnJsonDataFromDatabase(values[0]);
return jsonData;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
jsonData = result;
}
}
And in other class i use it like:
private static String returnJsonDataBackgroundTaskExecute(String fromWhichTableGetData) {
try {
return new BackgroundDatabaseTask().execute(fromWhichTableGetData).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return "Error in BackgroundDatabaseTask";
}
But get() block my main thread.
So, how can I get result of my async task in other non activity class?
I want run this in not activity class, so my class don't have onCreate method, but I have activity from my MainActivity class.
UPDATE:
Now i solve this problem using thread but it is a good solution?
Runnable runnable = new Runnable() {
#Override
public void run() {
listOfDataFromDatabase = GetterDataFromDatabase.returnJsonDataBackgroundTaskExecute(tableNameFromWhichIGetData);
}
};
Thread thread = new Thread(runnable);
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
now i have acces to this varaible listOfDataFromDatabase in other method .
An AsyncTask creates a new thread to perform a task that takes a long time. You start this thread by calling execute(). However, you immediately call get() which waits for the task to finish. This completely destroys the whole point of using an AsyncTask in the first place.
Instead, you should remove the call to get() and do the final processing in onPostExecute(). You can do whatever you wish in this method. There is absolutely no requirement that you use the Activity in any way. You can provide data to other classes if that is what you wish.
You can define an interface in your Asynctask class then implement it where ever you want and get the result from that interface callback
MyTask extends AsynTask{
public interface DataListener{
void onDataReceived(String result);
}
/// then on your onPostExecute method , get an instance of the interface then push the result to the interface method
dataListener.onDataReceived(result);
}
maybe this will help
I'm struggling with a network connection class I've created. The result of the Runnable I create returns a JSON object that contains all the information needed from the server. The thread runs, and receives the data perfectly, but of course, the program keeps running in the meantime, which results in a JSONException as being NULL.
I created a class called NetworkManager, which has the following method (jsonResponse is initialized at the beginning of the class)
JSONObject jsonResponse;
public void createNetworkThread(Context context, final String requestURI, final RequestBody formParameters) {
Runnable runnable = new Runnable() {
#Override
public void run() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(requestURI).post(formParameters).build();
Response response = null;
try {
response = client.newCall(request).execute();
String stringResponse = response.body().string();
NetworkManager.this.jsonResponse = new JSONObject(stringResponse);
// This works perfectly, "message" is received and printed to the log //
Log.d("Net", NetworkManager.this.jsonResponse.getString("message"));
} catch (IOException e) {
Log.d("Net", "Failed");
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
The above is called from the Activity, as:
Net.createNetworkThread(SignupActivity.this, requestURI, formVars);
JSONObject jsonResponse = Net.jsonResponse;
The JSON object jsonResponse is returning as NULL because the Thread is still accessing the server for the response.
I need to figure out how to stop the jsonResponse Object from being populated by Net.jsonResponse until the thread completes in order to stop it from returning NULL.
Any help?
I would only agree to the comments on your question and let you know, what you can do here.
If you are creating a thread just to get of the main UI thread to do the Network call you probably want to use OkHttp feature which allows you to get the Network call off the thread and provides you with callbacks to get the result something like this. you can check some example here
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(Response response) throws IOException {
// this is the callback which tells you the network call was successful, If like to make some changes to UI, you should call `runOnUiThread`.
"YourClassName".this.runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
}
});
or you can use AsyncTask which also gets your job done off the main UI thread and gives you the result in the callbacks.
private class MyTask extends AsyncTask<Void, Void, Void> {
//you can change the Type Void, Void, Void here to something which you want
//First Void belongs to doInBackground(Void... avoid)
//Second Void belongs to onProgressUpdate(Void... progress)
//Third Void belongs to onPostExecute(Void result)
// you may change these as you fit,
//when you want to start this class with your argument you can do something like this.
//new MyTask().execute("your argument to doInBackground");
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
// this is the method where you provide your implementation for doing a task off the main UI thread.
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// in this callback you are back in the main UI thread to make changes to UI depending on your response
}
}
here is an example of AsyncTask
If you want to offload the main thread, you should consider that the parallel task could finish it's execution after, generally speaking, any amount of time. Sure, you can wait in the main thread for the child thread to finish (using 'join()'), though this is kind of questionable in terms of speed gain.
Anyway, answering your question:
I need to figure out how to stop the jsonResponse Object from being
populated by Net.jsonResponse until the thread completes in order to
stop it from returning NULL.
I suggest you change
public void createNetworkThread(...
to
public Thread createNetworkThread(...
{
...
Thread thread = new Thread(runnable);
thread.start();
return thread;
}
And consequently
Thread t = Net.createNetworkThread(SignupActivity.this, requestURI, formVars);
t.join(); // Wait until 't' finishes -- try-catch is omitted for the sake of demo.
JSONObject jsonResponse = Net.jsonResponse;
This, apparently, opens question of performance, since main thread will be effectively completely blocked by 't.join()' until the child thread will finish.
Answering the question in the topic: in Java 8 you can use lambda functional interface like this:
package multithreaded;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Multithreaded {
public static void main(String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger("Main");
Worker<String, String> worker = new Worker<String, String>(
(String s) ->
{ // This is actual call-back code.
// It will be called by method 'apply' of interface 'Function' in the 'Worker'.
// It will accept String parameter and pass it in this block as variable 's'
logger.info("Embrace the beauty and power of Java 8! "+s); // yes, we can use local variables of the parent thread.
return "Call-Back "+s;
}
);
logger.info("Application starts new Worker.");
worker.start();
logger.info("Worker is running in background.");
Thread.currentThread().sleep(500); // Simulate some activity here...
logger.info("Result is unpredictable (could be null): "+worker.getResult());
// Wait here until worker is fully finished
worker.join();
logger.info("Result is predictable: "+worker.getResult());
}
}
Worker.java:
package multithreaded;
import java.util.function.Function;
public class Worker<T extends String, R extends String> extends Thread {
private final Function<T, R> callBack;
private volatile R result;
public Worker(Function<T, R> callBack)
{ this.callBack = callBack; }
#Override
public void run()
{
try{
int i = (int)(Math.random()*1000);
// simulate some activity unpredictable in terms of duration
Thread.currentThread().sleep(i);
// After "activity" is finished -- call the call-back function and get result in local variable.
// (Synchronization ommited for the sake of simplicity)
result = this.callBack.apply((T)("Result "+i)); // now let's call the call-back function and save the result in local variable.
}
catch(InterruptedException e)
{e.printStackTrace();}
}
// Getter for the local variable, populated by call-back function.
// (Synchronization ommited for the sake of simplicity)
public R getResult()
{ return this.result; }
}
Running above code multiple times, you will notice that from the parent thread's perspective the result is still unpredictable until the child thread is completely finished.
P.s. I suggest you re-think entire logic of data processing in your app and consider re-factoring towards entirely independent multi-threaded processing (perhaps using producer-consumer logic).
I'm trying to fix this code:
public class Async_Test extends AsyncTask<String, String, String> {
private String Response;
#Override
protected String doInBackground(String... params)
{
String tmp = "something";
return tmp;
}
#Override
protected void onPostExecute(String result) {
Response = result;
}
public String getResponse()
{
return this.Response;
}
}
The problem is the following: The getResponse() method is always null.
The execution code:
public void onClick(View v) {
try{
Async_Test t = new Async_Test();
t.execute("");
showMainText("res: "+t.getResponse());
} catch(Exception e)
{
showMainText(e.toString());
}
}
An async task is asynchronous. More precisely, here is what's going on when you call the execute() method :
a new thread is created.
the doInBackground(...) is executed on this new thread
when doInBackground(...) terminate : onPostExecute is executed on the main thread.
Therefore, when you call showMainText("res: "+t.getResponse()); (it's in the main thread): the onPostExecute didn't run yet and Response is still null.
To see the effect of AsyncTask: you can put a breakpoint on line :
showMainText("res: "+t.getResponse());
and you will see that the displayed text will be "something" (due to the breakpoint : the AsyncTask will have time to be executed.)
To get the result you expect : move the line showMainText("res: "+t.getResponse()); in the onPostExecute
I am getting the following java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() when trying to get the new instance of a
classObject.getNewInstance().
Everything I have read involved altering the UI thread. Is that the case here? If so, how to I get around this exception?
Code (Example used):
public class MainActivityAsyncClass extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
postData(params[0]);
return null;
}
public void postData(String methodToRun) {
Class[] noParams = {};
try {
Class mainActivityClass = Class.forName("com.MainActivity");
Method asyncRun = mainActivityClass.getDeclaredMethod(methodToRun, noParams);
Object obj = mainActivityClass.newInstance(); //<-- Error is thrown here
asyncRun.invoke(obj, null);
} catch(Exception e){
Util.appendLog("Error in async task. Exception: " + e.getMessage() + " " + e.getStackTrace());
}
}
}
in an AsyncTask :
doInBackground - invoked on background Thread, used to perform background computation.
onPostExecute - Invoked on the UI thread after the background computation finishes.All UI updates/Launching New Activity must be done on onPostExecute function of AsyncTask.
Refer the following documentation
Add the following to your AsyncTask to make it work :
protected void onPostExecute(Long result) {
postData(methodToRun);
}
methodToRun can be a member variable
I have an async task. It runs a sql query.It should go to the onPostExecute automatically, but it does not always go there. THere is no exception.The logs are also fine.
class QueryDbTask extends AsyncTask<String, Void, Cursor> {
protected Cursor doInBackground(String... params) {
....
//sql query
try {
cur=activityObject.execSQL(Query);
}catch (Exception e) {
e.printstacktrace
}
return cur;}
protected void onPostExecute(Cursor result) {
}
Under what conditions onPostExecute would not be called?
i debugged and found that it was not reaching onPost Execute
Can two async task simulataneoulsy?
onPostExecute() would not be called if doInBackground() never finished or if the task was interrupted/cancelled in which case onCancelled() would be called.
You have to put an #Override annotation to onPostExecute() to be called
#Override
protected void onPostExecute(Cursor result) {
....
}