I am new to rxAndroid. I use the following method with AsyncTask and I would like to convert it to RXjava.
mytask = new AsyncTask<long[], Void, Void>() {
Void doInBackground(long[] ... longs) {
for (long user : longs[0]) {
if (isCancelled())
return null;
try {
call(user);
} catch {
//
}
return null;
}
#Override
protected void onProgressUpdate(Void... voids) {
adapter.removeItem(0);
}
void onPreExecute() {
adapter.setBlocked(true);
}
void onPostExecute(Void aVoid) {
onStop();
}
void onCancelled() {
onStop();
}
void onStop() {
adapter.setBlocked(false);
}
}
.execute(adapter.getRemoveList());
}
I need help converting this AsyncTask to RxJava using the RxAndroid library.
Observable.just(input) // your input goes here
.map(input -> { //doInBackground with input goes here})
.subscribeOn(Schedulers.io())// take cares of doing task in background thread
.observeOn(AndroidSchedulers.mainThread())// make sures to deliver result on main thread
.doOnSubscribe(() -> {
// pre execute logic goes here
})
.subscribe(_ -> {
//post execute goes here
});
Related
I am facing with the problem. As far as I know zip method from RxJava waits for all observables to complete.
But am I getting another behaviour.
Here is my code snippet
private PublishSubject<Void> firstSubject;
private PublishSubject<Void> secondSubject;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadData();
mDrawerHeaderView.postDelayed(new Runnable() {
#Override
public void run() {
// getSecondSubject().onNext(null);
}
}, 1000);
mDrawerHeaderView.postDelayed(new Runnable() {
#Override
public void run() {
getFirstSubject().onCompleted();
}
}, 1000);
}
protected PublishSubject<Void> createFirstSubject() {
firstSubject = PublishSubject.create();
return firstSubject;
}
protected PublishSubject<Void> createSecondSubject() {
secondSubject = PublishSubject.create();
return secondSubject;
}
protected PublishSubject<Void> getFirstSubject() {
return firstSubject;
}
protected PublishSubject<Void> getSecondSubject() {
return secondSubject;
}
private void loadData() {
Observable<Void> firstSubject = createFirstSubject();
Observable<Void> secondSubject = createSecondSubject();
Observable<Boolean> allDataTask = Observable.zip(firstSubject, secondSubject, new Func2<Void, Void, Boolean>() {
#Override
public Boolean call(Void aVoid, Void aVoid2) {
return true;
}
});
allDataTask
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Boolean>() {
#Override
public void onCompleted() {
Notifications.showSuccessMessage(getApplicationContext(), "COMPLETE");
}
#Override
public void onError(Throwable e) {
Notifications.showErrorMessage(getApplicationContext(), "ERROR");
}
#Override
public void onNext(Boolean aBoolean) {
Notifications.showSuccessMessage(getApplicationContext(), "NEXT");
}
});
}
In this case I got COMPLETE message, but I was expecting to get nothing because the second subject is not completed.
What I am doing wrong ?
Please help me to get desired behaviour.
Yes, it works as expected. It makes perfect sense to receive the onCompleted() here, because if one stream is done, as long as all the elements it emitted are "zipped", there's no way to "zip" anything more, so it's "completed". You can also play with the sequence here.
I have to update the list after optimizing the running apps ....
m_optimizeBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
launchProgressRing(OptimizationActivity.this);
listAdaptor.notifyDataSetChanged();
}
});
}
Killing the running process in a seprate thread....
public void launchProgressRing(Context ctx){
final ProgressDialog opt_proDialog=new ProgressDialog(ctx);
opt_proDialog.setTitle("Please wait...");
opt_proDialog.setMessage("Optimizing power draining apps...");
opt_proDialog.setIndeterminate(true);
opt_proDialog.show();
opt_proDialog.setCancelable(false);
new Thread(new Runnable()
{
#Override
public void run()
{
//TODO: optimize apps
m_cPowerDrainingApps.killBgRunningProcesses(runningAppsList);
try
{
Thread.sleep(1500);
} catch (InterruptedException e)
{
e.printStackTrace();
}
runOnUiThread(new Runnable()
{
#Override
public void run()
{
opt_proDialog.dismiss();
}
});
}
}).start();
}
listAdaptor.notifyDataSetChanged() is not working ,don't know why ???
What I suggest is to use AsyncTask to do the job. AsyncTask has two good methods for you:
doInBackground: which you can put most of the background tasks in there
onPostExecute : which you can put the logic of what needs to be done when the background task has finished its job.
So your code should look like this:
public class BackgroundTask extends AsyncTask<Void,Void,Void>{
private ListAdapter mAdapter;
public BackgroundTask(ListAdapter adapter)
{
mAdapter = adapter
}
public Void doInBackground (Void... params)
{
//define m_cPowerDrainingApps somewhere
m_cPowerDrainingApps.killBgRunningProcesses(runningAppsList);
try
{
Thread.sleep(1500);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
public Void onPostExecute (Void... params)
{
//do your UI things
mAdapter.notifyDataSetChanged();
}
}
and then run this with:
new BackgroundTask(listAdapter).execute()
Use a Handler and its postDelayed method to invalidate the list's adapter as follows:
final Handler handler = new Handler()
handler.postDelayed( new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
handler.postDelayed( this, 60 * 1000 );
}
}, 60 * 1000 );
You must only update UI in the main (UI) thread.
I am calling a web service using AsyncTask in a android app and I can not figure out how to wait until the onPostExecute has finished:
//Call Async Web Service here
AsyncCallWS task = new AsyncCallWS();
task.execute();
//Need to wait to fill this in ** Its not waiting.
String sCall = rslt;
String[] aCall = sCall.split("//|");
private class AsyncCallWS extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
#Override
protected Void doInBackground(Void... params) {
Log.i(TAG, "doInBackground");
GetURL();
return null;
}
#Override
protected void onPostExecute(Void result) {
Log.i(TAG, "onPostExecute");
try{
//Results HERE
rslt = resultString.toString();
}
catch(Exception ex)
{rslt = ex.toString()+ "|" + ex.toString();}
}
}
I'm not clear on what you can't/don't want to do from onPostExecute but you can use a callback if you are wanting to execute something that's not coupled to the task (so that you can run the task from anywhere)
private class OnFinishedListener {
void onFinished(String rslt);
}
private class AsyncCallWS extends AsyncTask<Void, Void, Void> {
private OnFinishedListener mAfter;
public AsyncCallWS(OnFinishedListener after) {
mAfter = after;
}
...
#Override
protected void onPostExecute(Void result) {
....
if (mAfter != null) {
//you didnt illustrate what resultString is, you might
//want this to be the returned value from doInBackground
mAfter.onFinished(resultString.toString());
}
}
}
Usage
new AsyncCallWS(new OnFinishedListener {
public void onFinished(String rslt) {
//for example
String sCall = rslt;
String[] aCall = sCall.split("//|");
}
}).execute();
You can use Tasks.await(task) in a background thread. Do not use this in UI thread. You can also set timeout for your task Tasks.await(task, 500, TimeUnit.MILLISECONDS);
Use the getStatus() method.
while (task.getStatus() != Status.FINISHED);
A better way to do this would be to call split() inside the onPostExecute() method, since onPostExecute() runs on the UI thread anyway and the while() call would block the current thread it's running in.
I have a function which makes a http request and parses the response json data. The function is called in AsyncTask class. I have a function defined to check if there is connectivity before asynctask is invoked. But once the connection checker function returns true...my function runs within the asynctask class and the device loses connectivity the application force closes.
private void parseJson()
{
// HTTP request and JSON parsing done here
}
class getData extends AsyncTask <Void,Void,Void>
{
#Override
protected Void onPreExecute(Void...arg0)
{
super.onPreExecute();
//progress dialog invoked here
}
#Override
protected Void doInBackground(Void...arg0)
{
parseJSON();
return null;
}
#Override
protected Void onPostExecute(Void...arg0)
{
super.onPostExecute();
//UI manipulated here
}
}
how do i notify the user about the exception occuring in the doInBackground() method and handle exception properly since doInBackground() doesn't allow things like firing a toast message.
Do this Way
class getData extends AsyncTask <Void,Void,Boolaen>
{
#Override
protected Void onPreExecute(Void...arg0)
{
super.onPreExecute();
//progress dialog invoked here
}
#Override
protected Boolaen doInBackground(Void...arg0)
{
try{
parseJSON();
return true;
}catch(Exception e){
e.printStackStrace();
}
return false;
}
#Override
protected Void onPostExecute(Boolaen result)
{
super.onPostExecute(result);
if(result){
//success
}else{
// Failure
}
//UI manipulated here
}
}
My approach looked like this. Introducing a generic AsyncTaskResult, where you can either store your real return value (if you need one) or the exception which occured in doInBackground(). In onPostExecute you can check if an exception has occured and notify your user (or process your return value).
AsyncTaskResult:
public class AsyncTaskResult<T> {
private T mResult;
private Exception mException = null;
public AsyncTaskResult() {
}
public AsyncTaskResult(T pResult) {
this.mResult = pResult;
}
public AsyncTaskResult(Exception pException) {
this.mException = pException;
}
public T getResult() {
return mResult;
}
public boolean exceptionOccured() {
return mException != null;
}
public Exception getException() {
return mException;
}
}
AsyncTask:
public class RessourceLoaderTask extends AsyncTask<String, String, AsyncTaskResult<String>> {
public RessourceLoaderTask() {
}
#Override
protected AsyncTaskResult<String> doInBackground(String... params) {
try {
// Checked Exception
} catch (Exception e) {
return new AsyncTaskResult<String>(e);
}
return new AsyncTaskResult<String>();
}
#Override
protected void onPostExecute(AsyncTaskResult<String> pResult) {
if (!pResult.exceptionOccured()) {
//...
} else {
// Notify user
}
}
}
Make a field in getData class. Set it in doBackground, check it in onPostExecute.
How would I call this function in asynctask?
void somefunc()
{
tr1 = (TableRow) new TableRow(this);
//error
txt1=new TextView(this);
txt9.setText(strinarr[0]);
tr1.addView(txt1);
tl.addView(tr1,new TableLayout.LayoutParams(layoutParams));
}
class SaveAdDetail extends AsyncTask<Void, String, Void>
{
#Override
public void onPreExecute()
{
super.onPreExecute();
Progdialog = ProgressDialog.show(demotable.this, "", "Please Wait...", true);
Progdialog.show();
}
#Override
public Void doInBackground(Void... unused)
{
try
{somefunc();}
catch (Exception e)
{strdata="Error";}
return null;
}
#Override
public void onPostExecute(Void unused)
{
Progdialog.dismiss();
if(strdata.equals("Error"))
{Toast(strdata);}
else
{
Toast("asdasdasd");
}
}
}
You have a choice : use handlers or call directly. In both cases you should pass a reference to the constructor of AsyncTask. onPostExecute() is called on the UI thread, so you can call the method directly on the reference of your activity.
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Constants.TASK_FINISHED:
somefunc();
break;
}
}
};
SaveAdDetail task = new SaveAdDetail(handler);
task.execute();
// in your SaveAdDetail:
#Override
public void onPostExecute(Void unused) {
Progdialog.dismiss();
handler.obtainMessage(Constants.TASK_FINISHED).sendToTarget();
}
I would use a Handler. Here is an example: http://developer.android.com/resources/articles/timed-ui-updates.html