Id like to manipulate a specific view in an async task before the backround task executes but not sure how I can pass the required parameters to the method. I Just get a null pointer when I do something like this
class CalcFib extends AsyncTask<Integer, Void, Long> {
private View v;
private int index;
public CalcFib(int i){
this.index = i;
}
#Override
protected void onPreExecute() {
//do something with this.index
}
#Override
protected Long doInBackground(Integer... params) {
long t = 1234;
return t;
}
#Override
protected void onPostExecute(Long result) {
}
}
Add a constructor to CalcFib and pass the required values to an instance through the constructor.
Related
I have an IME service class and a long operation method in it. I want to run the LongOperation task in a asyncTask class that is in the IME Service class.
public class Myimeservice extends InputMethodService
implements KeyboardView.OnKeyboardActionListene {
//...
//some code here....
//...
public void setDictionary(){
//....
}
private class LongOperation extends AsyncTask<String, Void, String> {
private Myimeservice parent;
public LongOperation(Myimeservice pim){
parent = pim;
}
#Override
protected String doInBackground(String... params) {
Myimeservice tmp = new Myimeservice();
tmp.setDictionary();
return "Executed";
}
#Override
protected void onPostExecute(String result) {
//app.hideLoading();
}
#Override
protected void onPreExecute() {
//app.showLoading();
}
#Override
protected void onProgressUpdate(Void... values) {}
}
When i run it, the application forced to close. please help me.
I think the error is somewhere in your public void setDictionary() method.
I assume that you are manipulating a variable that is bound to the UIThread/MainThread, the application will crash since doInBackground is on another Thread.
Instead make the setDictionary() method return the dictionary and return it instead of "Executed" in doInBackground().
This will call the onPostExecute(Object result) which is run on UIThread/MainThread.
Something like this:
private class LongOperation extends AsyncTask<String, Void, Dictionary> {
#Override
protected Dictionary doInBackground(String... params) {
Myimeservice tmp = new Myimeservice();
Dictionary dict = tmp.setDictionary();
return dict;
}
#Override
protected void onPostExecute(Dictionary result) {
//do what ever you meant to do with it;
}
}
If you are not expecting any result from it you can just do:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
tmp.setDictionary();
}
});
I use the Runnable instead of AsyncTask and the problem solved.
final Runnable r = new Runnable(){
public void run(){
setDictionary();
}
};
this code is in onCreate() method of service.
Tanks a lot Tristan Richard.
I have an implementation of onItemClick() while selecting from a list of items. However inside
onItemClick() I need to perform a check via a library call that is async. Basically within onItemClick() a call to XYZ.checkConnection(booleanCallback); is made which is async.
And then in booleanCallback(int status) I can check for the status. What kind of pattern can I use to handle this scenario?
public class Tester extends Activity {
private ListView list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
new CheckConnection(list.getAdapter().getItem(position))
.execute();
}
});
}
private class CheckConnection extends AsyncTask<Void, Void, Void> {
private Object o;
public CheckConnection(Object o) {
this.o = o;
}
#Override
protected void onPreExecute() {
// Do things like initiate progress bar etc
}
#Override
protected Void doInBackground(Void... params) {
// Do connection check
return null;
}
#Override
protected void onPostExecute(Void result) {
int status = 0;
// determine status
booleanCallBack(status, o);
}
}
private void booleanCallBack(int status, Object o) {
// perform UI related
}
}
you use the delegate approach if you want a modular class
I have essentially given you a starting point,this can be tweaked based on what you want.I didnt exactly get your context.hence the generalised answer
I am quite new to Android Development. I am working in a app where i need to make a lot of async calls to api. For each and every API call, I have to write the similar looking AsyncTask class over and over again. So, is there any way to make these Async Calls modular?
yes it is possible use Listener and AsyncTask with parameterized constructor
Check it
Create an interface
public interface OnTaskCompletListerner {
void oncompleteListerner(String name);
}
create an AsyncTask class as follows
public class AsyncTaskModuler extends AsyncTask<Void, Void, String> {
private Context context;
private HashMap<String, String> data;
private String URL;
private OnTaskCompletListerner taskdone;
public AsyncTaskModuler(Context ctx,HashMap<String, String> data,String url,OnTaskCompletListerner taskdone){
this.context=ctx;
this.data=data;
this.URL=url;
this.taskdone=taskdone;
}
#Override
protected String doInBackground(Void... params) {
//Do the task here and return the value if needed
return null;
}
#Override
protected void onPostExecute(String result) {
taskdone.oncompleteListerner(result);
}
and call it in your activity like this
public class CallAync extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String url="";
HashMap<String, String> data=new HashMap<String, String>();
AsyncTaskModuler moduler=new AsyncTaskModuler(CallAync.this, data, url, completListerner);
moduler.execute();
}
OnTaskCompletListerner completListerner=new OnTaskCompletListerner() {
#Override
public void oncompleteListerner(String name) {
}
};
}
Create an general async task and pass your url as param to it .Hence you can reuse the same async task for all your api calls
public class myTask extends AsyncTask<Void, Void, Void> {
String muUrl;
public myTask(Context context, Activity activity,
String url) {
contxt = context;
myUrl=url;
}
#Override
protected Void doInBackground(Void... params) {
makeApiCalls();
return null;
}
}
Start the task in the following way :
new myTask(this, this, urlStr).execute();
EDIT
How can I perform different logic onPostExecute() ?
You can add another param in the constructor of myTask.
Ex.
public MyTask(Context context, Activity activity,
String url,String postExecuteAction) {
}
In your post executes just check of each case in if else and perform the respective task
Dummy Background class
private class BackGroundClass extends AsyncTask<String, Void, Bitmap> //<arg to do InBackground,,returntype of do inBackground and arg of onPostExecut>
{
public BackGroundClass()
{
}
#Override
protected void onPreExecute() //forground work in UI thread prior to doInbackground
{
super.onPreExecute();
}
#Override
protected Bitmap doInBackground(String... urls) //background work in parallel thread
{
Bitmap b=null;
// your background work
return b;
}
#Override
protected void onPostExecute(Bitmap result) //forground work in UI thread post to doInbackground
{
super.onPostExecute(result);
if(result!=null)
{
//use bitmap image in result
}
else
{
//Image is not available
}
}
}
Calling for one parellel execution
new BackGroundClass().execute(StringArg1,stringArg2,StringArg3);
Calling for multiple parellel execution
when tou need to call more than one background task at same time
new BackGroundClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,StringArg1,stringArg2,StringArg3);
Called from single activity
use this as an inner class to your activity for making it easy to share variable if not called from more than one activity
Called from more than one activity
use constructor to pass activity context,and other variable
new BackGroundClass(constructor arguments).execute(StringArg1,stringArg2,StringArg3);
new BackGroundClass(constructor arguments).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,StringArg1,stringArg2,StringArg3);
I have AsyncTask and my progress in background is in infinite loop. But I need to stop AsyncTask when user stop my app or go back from my app (my app go to foreground). How can I do it?
Solution:
private boolean done = false;
private class CurTask extends AsyncTask<String, Void, Object> {
protected Void doInBackground(String... args) {
while(!done){
DefaultCurProgress();
publishProgress();
}
}
protected void onProgressUpdate(Void...unused) {
textCur = (TextView)findViewById(R.id.text_cur);
SharedPreferences myPrefs = MyActivity.this.getSharedPreferences("myPrefs", MODE_PRIVATE);
String prefNameDefaultCur = myPrefs.getString(DefaultCur, "");
textCur.setText(prefNameDefaultCur);
}
}
#Override
public void onPause(){
super.onPause();
done=true;
}
#Override
public void onResume(){
super.onResume();
done=false;
}
Declare a method within your AsyncTask that tells it to end. Something like so:
private class CurTask extends AsyncTask<String, Void, Object> {
private boolean done = false;
public void quit() {
done = true;
}
protected Void doInBackground(String... args) {
while(!done){
DefaultCurProgress();
publishProgress();
}
}
Add a boolean member variable and use that in your while condition instead of true.
Then when you need to cancel it you can just call an instance method to set this variable to false, the doInBackground method will return and the task will finish.
I am using Async tasks to get string from the menu activity and load up some stuff..but i am
not able to do so..Am i using it in the right way and am i passing the parameters correctly?
Please see the code snippet. thanks
private class Setup extends AsyncTask<Void, Integer, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
if (!(getIntent().getExtras().isEmpty())) {
Bundle gotid = getIntent().getExtras();
identifier = gotid.getString("key");
}
} catch (Exception e) {
e.getStackTrace();
} finally {
if (identifier.matches("abc")) {
publishProgress(0);
db.insert_fri();
} else if ((identifier.matches("xyz"))) {
publishProgress(1);
db.insert_met();
}
}
return null;
}
#Override
protected void onProgressUpdate(Integer... i) {
// start the song here
if (i[0] == 0) {
song.setLooping(true);
song.start();
}
}
#Override
protected void onPostExecute(Void res) {
}
#Override
protected void onPreExecute() {
// do something before execution
}
}
Avoid adding a constructor.
Simply pass your paramters in the task execute method
new BackgroundTask().execute(a, b, c); // can have any number of params
Now your background class should look like this
public class BackgroundTask extends AsyncTask<String, Integer, Long> {
#Override
protected Long doInBackground(String... arg0) {
// TODO Auto-generated method stub
String a = arg0[0];
String b = arg0[1];
String c = arg0[2];
//Do the heavy task with a,b,c
return null;
}
//you can keep other methods as well postExecute , preExecute, etc
}
Instead of this i would do
private class Setup extends AsyncTask<String, Integer, Void> {
#Override
protected Void doInBackground(String... params) {
String identifier = params[0];
if (identifier.matches("abc")) {
publishProgress(0);
db.insert_fri();
} else if ((identifier.matches("xyz"))) {
publishProgress(1);
db.insert_met();
}
}
return null;
}
#Override
protected void onProgressUpdate(Integer... i) {
// start the song here
if (i[0] == 0) {
song.setLooping(true);
song.start();
}
}
#Override
protected void onPostExecute(Void res) {
}
#Override
protected void onPreExecute() {
// do something before execution
}
}
and check for "identifier" before invoking the asynctask to prevent overhead of creating a AsyncTask
like this
if (!(getIntent().getExtras().isEmpty())) {
Bundle gotid = getIntent().getExtras();
identifier = gotid.getString("key");
new Setup().execute(identifier);
}
A simple way is to add a constructor:
public Setup(String a, Int b) {
this.a = a;
this.b = b;
}
AsyncTask means doInBackground() returns Void, onProgressUpdate() takes Integer params and doInbackground takes... String params !
So you don't need (and REALLY shouldn't) use Intent, since it is meant to be used for passing arguments through Activities, not Threads.
And as told before, you can make a constructor and a global parameter to your class called "identifier"
public class Setup...
{
private String identifier;
public Setup(String a) {
identifier = a;
}
}
Hoped it could help.
Regards