Observable.create(new Observable.OnSubscribe<Integer>() {
public void call(final Subscriber<? super Integer> obs) {
new Thread(){
public void run(){
obs.onNext(1);
}
}.start();
new Thread(){
public void run(){
obs.onNext(2);
}
}.start();
new Thread(){
public void run(){
obs.onNext(3);
}
}.start();
obs.onCompleted();
}
}).subscribe(new Subscriber<Integer>(){
public void onCompleted() {
System.out.println("Complete");
}
public void onError(Throwable arg0) {
// TODO Auto-generated method stub
}
public void onNext(Integer arg0) {
System.out.println(arg0);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
As you see , I want to do multi-threading on Java with RxJava
I've studied many resources on Google , but most of them are for Android
Can anybody tell what is the easiest way to implement it ?
I think my code is a little :<
Well, it's a bit unclear what you're asking, but it is worthwhile to at least have a cursory read over the Observable class, as it has a lot of methods that will make your life easier. For example, your code roughly translates to:
Observable
.just(1,2,3)
.subscribeOn(Schedulers.io())
.zipWith(Observable.interval(1000,1000,TimeUnit.milliseconds),
(item, pos) -> item)
.doOnCompleted(() -> System.out.println("Complete");
.subscribe(item -> System.out.println(item));
However, you first need to be clear on what do you want to do - can you put it to words?
Related
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
});
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 codes below that will execute a callback from another thread when I finish the activity. So how to avoid to call the callback or the codes in the callback when the activity has been finished?
public static interface Callback{
public void onCallback();
}
class ActivityA {
TextView tv = ...;
Handler handler = ...;
public void onClick(View v) {
Business.callThread(new Callback() {
#Override
public void onCallback() {
handler.post(new Runnable(){
public void run(){
tv.setText("xxxx");
}
});
}
});
}
}
class Business {
public static void callThread(final Callback listener) {
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000); //sleep 5s;
} catch (InterruptedException e) {
e.printStackTrace();
}
listener.onCallback();
}
}).start();
}
}
Garbage collector counts references to objects. However, there are couple of reference types. Useful in your case is WeakReference:
Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed.
Create runnable as a class with constructor:
static class CallbackRunnable implements Runnable {
WeakReference<Callback> listener;
public CallbackRunnable(Callback listener) {
this.listener = new WeakReference<Callback>(listener);
}
#Override
public void run() {
try {
Thread.sleep(5000); //sleep 5s;
} catch (InterruptedException e) {
e.printStackTrace();
}
if (listener.get() == null) {
return;
}
listener.get().onCallback();
}
}
then call listener like:
if (listener.get() == null) {
return;
}
listener.get().onCallback();
callThread method implementation:
public static void callThread(final Callback listener) {
new Thread(new CallbackRunnable(listener)).start();
}
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 have this code:
if (value) {
thread = new Thread() {
#Override
public void run() {
try {
while (!isConnected()) {
synchronized (this) {
wait(3000);
}
}
} catch (InterruptedException ex) {
}
if(wifiManager.isWifiEnabled()){
sendMessageWidget();
} else {
showWifiSettingsAlert();
}
}
};
thread.start();
}
I want my app to wait until google api client is connected and than send a message.
The code for the isConnected method is:
public boolean isConnected() {
mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected()) {
return true;
}
return false;
}
But I get this error message:
NullPointerException: Can't create handler inside thread that has not called Looper.prepare(), and it says that the mistake is somewhere id showWifiSettingsAlert()
here is the code:
public void showWifiSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
// Setting Dialog Title
alertDialog.setTitle("Location accuracy tips");
// Setting Dialog Message
alertDialog
.setMessage("You can improve the accuracy of your location by turning on\n- Wi-Fi");
// On pressing Settings button
alertDialog.setPositiveButton("Turn on",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
wifiManager.setWifiEnabled(true);
// Posalji poruke al pre toga jos jednom azuriraj
// lokaciju al ako je pozvana aplikacija iz widgeta
if (value) {
sendMessageWidget();
}
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
wifiManager.setWifiEnabled(false);
// Posalji poruke al pre toga jos jednom azuriraj
// lokaciju al ako je pozvana aplikacija iz widgeta
if (value) {
sendMessageWidget();
}
}
});
// Showing Alert Message
alertDialog.show();
}
I want, if wifi is not enabled, the user to choose to enable it or not, but either way the message should be sent... can you help please?
Since you can't touch the UI from a thread other than the main thread, you must post these changes back to the UI thread and its looper and associated handlers. You can do so explicitly by creating a handler associated with the UI thread (which will work anywhere, since Looper.getMainLooper() is a static call) such as:
if (value) {
Handler uiCallback = new Handler(Looper.getMainLooper());
thread = new Thread() {
#Override
public void run() {
try {
while (!isConnected()) {
synchronized (this) {
wait(3000);
}
}
} catch (InterruptedException ex) {
}
uiCallback.post(new Runnable() {
#Override public void run() {
if(wifiManager.isWifiEnabled()){
sendMessageWidget();
} else {
showWifiSettingsAlert();
}
}
});
}
};
thread.start();
}
Or instead of using a handler at all, you can wrap the part in the run() method in runOnUiThread() if you are in an activity which does the same thing.
You should note however, you don't actually need to use any threading here. If you follow the example on: https://developer.android.com/google/auth/api-client.html you'll find that by implementing ConnectionCallbacks, OnConnectionFailedListener you can call mGoogleApis.connect() from the activity's onStart() and when it connects or fails to do the corresponding callback will be executed on the calling thread. For instance,
#Override
public void onConnected(Bundle connectionHint) {
if(wifiManager.isWifiEnabled()){
sendMessageWidget();
} else {
showWifiSettingsAlert();
}
}
Achieves the same thing...
You are using mGoogleApiClient.connect();, which is an asynchronous method, in a thread and this isn't allowed.
You could try using runOnUiThread instead :
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//do your stuff here
}
});