How to get local variable from Runnable Thread
I have a helper class (not for activity) that makes a request to an API that has a public function called run()
and runs on a new thread (as per Android spec). Mine MainActivity
creates a new object MakeQuery
and runs its function run()
:
MakeQuery q = new MakeQuery();
q.run();
However, I need to access the variable from the stream. Below is a sample code:
public class MakeQuery implements Runnable {
private void setNewString(String localThreadString){
//NewString comes out null...
NewString = localThreadString;
}
public void run() {
new Thread(new Runnable() {
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
API Api = new API(keys and tokens);
//queryAPI() returns string
setNewString(queryAPI(Api, term1, term2));
//Don't know how to send intent from here (No context),
//I would like:
Intent i = new Intent(MainActivity.class, AnotherActivity.class)
}
}).start();
}
AsyncTask
//This runs in background thread
@Override
protected Void doInBackground(Void... params) {
API Api = new API(keys and tokens);
setNewString(queryAPI(Api, string1, string2));
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
Intent intent = new Intent(mContext, Activity2.class);
intent.putExtra("NewString", NewString);
Log.d(MYTAG, NewString);
}
MainActivity
public void buttonPressed(View view) {
Intent intent = new Intent(this, Activity2.class);
...
MakeQuery task = new MakeQuery(this);
task.execute();
startActivity(intent);
}
I've been trying to watch online for hours. I tried to do AsyncTask
, but I'm not sure how to implement this with what I have. Also, using it localThread<String>
didn't help.
TL; DR: I would like to know if the NewString can be received so that I can pass it through the Intent for another action.
Solution
Don't use Runnable
, create a new AsyncTask
one as shown below. Also, make sure to be StartActivity
in the helper class and not in the MainActivity
. This happened because I was not waiting for the task to complete before starting a new activity.
source to share
Here's an implementation using an async task:
public class MakeQueryTask extends AsyncTask<Void, Void, Void> {
private Context mContext;
private String newString;
public MakeQueryTask(Context context) {
mContext = context;
}
//This runs on a background thread
@Override
protected Void doInBackground(Void... params) {
API Api = new API(keys and tokens);
//queryAPI() returns string
setNewString(queryAPI(Api, term1, term2));
//You should start your activity on main thread. Do it in onPostExecute() which will be invoked after the background thread is done
//Intent i = new Intent(mContext, AnotherActivity.class);
//mContext.startActivity(intent);
return null;
}
private void setNewString(String localThreadString){
newString = localThreadString;
}
//This will run on UI thread
@Override
protected void onPostExecute(Void aVoid) {
Intent intent = new Intent(mContext, AnotherActivity.class);
mContext.startActivity(intent);
}
}
And you do the following:
MakeQueryTask task = new MakeQueryTask(this); //Here this is an activity (context)
task.execute();
source to share
If you call this runnable
from activity
or service
, you can pass in the constructor context
. And just start the operation with intent
in a function run()
.
public class MakeQuery implements Runnable {
private Context context;
public MakeQuery(Context context) {
this.context = context;
}
private void setNewString(String localThreadString){
//NewString comes out null...
NewString = localThreadString;
}
public void run() {
new Thread(new Runnable() {
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
API Api = new API(keys and tokens);
//queryAPI() returns string
setNewString(queryAPI(Api, term1, term2));
Intent intent = new Intent(MainActivity.class, AnotherActivity.class)
context.startActivity(intent);
}
}).start();
}
source to share