How to get Flow Coroutine in Java with RxJava - java

I need to get a Coroutine Flow in my Java app. I try to test with RxJava but it's dosn't work for me
Single<Object> collect = Flowable.just(mContextServer.observeAllMessages()).collect(new Collector<Flow<Message>, Object, Object>() {
#Override
public Supplier<Object> supplier() {
Log.d(TAG, "supplier");
return null;
}
#Override
public BiConsumer<Object, Flow<Message>> accumulator() {
Log.d(TAG, "accumulator");
return null;
}
#Override
public BinaryOperator<Object> combiner() {
Log.d(TAG, "combiner");
return null;
}
#Override
public Function<Object, Object> finisher() {
Log.d(TAG, "finisher");
return null;
}
#Override
public Set<Characteristics> characteristics() {
Log.d(TAG, "characteristics");
return null;
}
});
someone would have a solution ?

Related

How to prevent fragment to refresh recyclerview when after back from another fragment / save recyclerview position

In this part I try to add one feature in my app and fix one problem, I would like to save the recyclerview position so when click and navigate to details fragment and click back, this should back to the same position, the issue here is when I click back I see the items overlapping, there are about 8 items and it starts from next list position, while I searching for the solution of this issue, I found this answer then I decided to add the dependencies of recyclerview separately implementation "androidx.recyclerview:recyclerview:1.2.1" to use this feature
adapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY);
but it doesn't work, the next GIF describe the problem
recyclerview position problem
and this example of the app with this feature
Target
HomeFragment
#AndroidEntryPoint
public class HomeFragment extends Fragment {
private FragmentHomeBinding binding;
private PostViewModel postViewModel;
public static final String TAG = "HomeFragment";
private PostAdapter adapter;
private List<Item> itemArrayList;
private GridLayoutManager titleLayoutManager, gridLayoutManager;
WrapContentLinearLayoutManager layoutManager;
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.homeRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(requireContext(),
binding.homeRecyclerView, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Item item = itemArrayList.get(position);
if (Objects.requireNonNull
(Navigation.findNavController(requireView())
.getCurrentDestination()).getId() == R.id.nav_home) {
Navigation.findNavController(requireView())
.navigate(HomeFragmentDirections.actionNavHomeToDetailsFragment(item));
}
}
#Override
public void onLongItemClick(View view, int position) {
}
}));
}
public View onCreateView(#NonNull LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
binding = FragmentHomeBinding.inflate(inflater, container, false);
setHasOptionsMenu(true);
postViewModel = new ViewModelProvider(this).get(PostViewModel.class);
postViewModel.finalURL.setValue(Constants.getBaseUrl() + "?key=" + Constants.getKEY());
itemArrayList = new ArrayList<>();
adapter = new PostAdapter(getContext(), itemArrayList, this, postViewModel);
layoutManager = new WrapContentLinearLayoutManager(requireContext(),
LinearLayoutManager.VERTICAL, false);
titleLayoutManager = new GridLayoutManager(getContext(), 2);
gridLayoutManager = new GridLayoutManager(getContext(), 3);
// binding.homeRecyclerView.setAdapter(adapter);
binding.shimmerLayout.setVisibility(View.VISIBLE);
binding.homeRecyclerView.setVisibility(View.INVISIBLE);
adapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY);
postViewModel.recyclerViewLayoutMT.observe(getViewLifecycleOwner(), layout -> {
Log.w(TAG, "getSavedLayout: called");
switch (layout) {
case "cardLayout":
binding.loadMoreBtn.setVisibility(View.VISIBLE);
binding.homeRecyclerView.setLayoutManager(layoutManager);
binding.homeRecyclerView.setAdapter(adapter);
adapter.setViewType(0);
break;
case "cardMagazineLayout":
binding.loadMoreBtn.setVisibility(View.VISIBLE);
binding.homeRecyclerView.setLayoutManager(layoutManager);
binding.homeRecyclerView.setAdapter(adapter);
adapter.setViewType(1);
break;
case "titleLayout":
binding.loadMoreBtn.setVisibility(View.GONE);
binding.homeRecyclerView.setLayoutManager(titleLayoutManager);
binding.homeRecyclerView.setAdapter(adapter);
adapter.setViewType(2);
break;
case "gridLayout":
binding.loadMoreBtn.setVisibility(View.GONE);
binding.homeRecyclerView.setLayoutManager(gridLayoutManager);
binding.homeRecyclerView.setAdapter(adapter);
adapter.setViewType(3);
}
});
if (Utils.hasNetworkAccess(requireContext())) {
postViewModel.getPosts();
postViewModel.postListMutableLiveData.observe(getViewLifecycleOwner(), postList -> {
itemArrayList.addAll(postList.getItems());
binding.shimmerLayout.stopShimmer();
binding.shimmerLayout.setVisibility(View.GONE);
binding.homeRecyclerView.setVisibility(View.VISIBLE);
adapter.notifyDataSetChanged();
Log.e(TAG, "ItemsArrayList :" + itemArrayList.get(0).getTitle());
});
} else {
binding.shimmerLayout.setVisibility(View.VISIBLE);
// binding.shimmerLayout.startShimmer();
if (postViewModel.getAllItemsFromDataBase == null) {
noInternetConnectionLayout();
} else {
// Log.e(TAG, "RoomDB Items size :" + itemsDatabase.itemDAO().getAlItems());
binding.shimmerLayout.stopShimmer();
binding.shimmerLayout.setVisibility(View.GONE);
binding.emptyView.setVisibility(View.GONE);
binding.homeRecyclerView.setVisibility(View.VISIBLE);
postViewModel.getAllItemsFromDataBase.observe(getViewLifecycleOwner(), items -> {
if (items.isEmpty()) {
noInternetConnectionLayout();
} else {
binding.loadMoreBtn.setVisibility(View.GONE);
itemArrayList.addAll(items);
adapter.notifyDataSetChanged();
}
});
}
}
postViewModel.errorCode.observe(getViewLifecycleOwner(), errorCode -> {
if (errorCode == 400) {
Snackbar.make(requireView(), R.string.lastPost, Snackbar.LENGTH_LONG).show();
} else {
binding.homeRecyclerView.setVisibility(View.INVISIBLE);
binding.emptyView.setVisibility(View.VISIBLE);
}
});
binding.loadMoreBtn.setOnClickListener(view -> {
AlertDialog dialog = Utils.setProgressDialog(requireContext());
postViewModel.isLoading.observe(getViewLifecycleOwner(), isLoading -> {
if (isLoading) {
dialog.show();
} else {
dialog.dismiss();
}
});
if (Utils.hasNetworkAccess(requireContext())) {
postViewModel.getPosts();
// Log.w(TAG, "loadMoreBtn: " + dialog.isShowing());
} else {
postViewModel.isLoading.postValue(true);
postViewModel.getAllItemsFromDataBase.getValue();
postViewModel.isLoading.postValue(false);
}
});
return binding.getRoot();
}
private void noInternetConnectionLayout() {
binding.shimmerLayout.stopShimmer();
binding.shimmerLayout.setVisibility(View.GONE);
binding.homeRecyclerView.setVisibility(View.GONE);
binding.emptyView.setVisibility(View.VISIBLE);
}
#Override
public void onDestroyView() {
super.onDestroyView();
itemArrayList.clear();
binding = null;
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
super.onCreateOptionsMenu(menu, inflater);
SearchManager searchManager = (SearchManager) requireContext().getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.app_bar_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(requireActivity().getComponentName()));
searchView.setQueryHint(getResources().getString(R.string.searchForPosts));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String keyword) {
if (keyword.isEmpty()) {
Snackbar.make(requireView(), "please enter keyword to search", Snackbar.LENGTH_SHORT).show();
}
if (Utils.hasNetworkAccess(requireContext())) {
itemArrayList.clear();
postViewModel.getItemsBySearch(keyword);
adapter.notifyDataSetChanged();
} else {
postViewModel.getItemsBySearchInDB(keyword);
postViewModel.getItemsBySearchMT.observe(getViewLifecycleOwner(), items ->
{
Log.d(TAG, "onQueryTextSubmit database called");
itemArrayList.clear();
itemArrayList.addAll(items);
adapter.notifyDataSetChanged();
}
);
}
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
searchView.setOnCloseListener(() -> {
if (Utils.hasNetworkAccess(requireContext())) {
Log.d(TAG, "setOnCloseListener: called");
itemArrayList.clear();
binding.emptyView.setVisibility(View.GONE);
binding.homeRecyclerView.setVisibility(View.VISIBLE);
postViewModel.getPosts();
adapter.notifyDataSetChanged();
} else {
Log.d(TAG, "setOnCloseListener: called");
binding.emptyView.setVisibility(View.GONE);
binding.homeRecyclerView.setVisibility(View.VISIBLE);
postViewModel.getAllItemsFromDataBase.observe(getViewLifecycleOwner(), items ->
{
itemArrayList.addAll(items);
adapter.notifyDataSetChanged();
}
);
}
return false;
});
postViewModel.searchError.observe(getViewLifecycleOwner(), searchError -> {
if (searchError) {
Toast.makeText(requireContext(),
"There's no posts with this keyword", Toast.LENGTH_LONG).show();
}
});
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if (item.getItemId() == R.id.change_layout) {
changeAndSaveLayout();
return true;
}
return super.onOptionsItemSelected(item);
}
The ViewModel
#HiltViewModel
public class PostViewModel extends ViewModel {
public static final String TAG = "PostViewModel";
private final com.blogspot.abtallaldigital.data.Repository repository;
public final MutableLiveData<PostList> postListMutableLiveData = new MutableLiveData<>();
public final MutableLiveData<String> finalURL = new MutableLiveData<>();
public final MutableLiveData<String> token = new MutableLiveData<>();
public final MutableLiveData<String> label = new MutableLiveData<>();
public final MutableLiveData<Integer> errorCode = new MutableLiveData<>();
public final MutableLiveData<Boolean> searchError = new MutableLiveData<>();
public final LiveData<List<Item>> getAllItemsFromDataBase;
public final MutableLiveData<List<Item>>
getItemsBySearchMT = new MutableLiveData<>();
public final MutableLiveData<Boolean> isLoading = new MutableLiveData<>();
public final MutableLiveData<String> recyclerViewLayoutMT = new MutableLiveData<>();
private final Utils.DataStoreRepository dataStoreRepository;
public final MutableLiveData<Integer> currentDestination = new MutableLiveData<>();
// public MutableLiveData<Boolean> ifAnythingWrongHappened = new MutableLiveData<>();
#Inject
public PostViewModel(Repository repository, Utils.DataStoreRepository dataStoreRepository) {
this.repository = repository;
getAllItemsFromDataBase = repository.localDataSource.getAllItems();
this.dataStoreRepository = dataStoreRepository;
dataStoreRepository.readLayoutFlow
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new FlowableSubscriber<String>() {
#Override
public void onSubscribe(#NonNull Subscription s) {
s.request(Long.MAX_VALUE);
}
#Override
public void onNext(String layout) {
if (layout != null) {
recyclerViewLayoutMT.setValue(layout);
}
}
#Override
public void onError(Throwable t) {
Log.e(TAG, "onError: " + t.getMessage());
Log.e(TAG, "onError: " + t.getCause());
}
#Override
public void onComplete() {
}
});
dataStoreRepository.readCurrentDestination
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.firstOrError().subscribeWith(new SingleObserver<Integer>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onSuccess(#NonNull Integer destination) {
currentDestination.setValue(destination);
}
#Override
public void onError(#NonNull Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
});
}
public void saveRecyclerViewLayout(String layout) {
dataStoreRepository.saveRecyclerViewLayout("recyclerViewLayout", layout);
}
public void saveCurrentDestination(int currentDestination) {
dataStoreRepository
.saveCurrentDestination("CURRENT_DESTINATION", currentDestination);
}
// #Override
// protected void onCleared() {
// super.onCleared();
// postListMutableLiveData.setValue(null);
// finalURL.setValue(null);
// token.setValue(null);
// }
public void getPosts() {
Log.e(TAG, finalURL.getValue());
isLoading.setValue(true);
repository.remoteDataSource.getPostList(finalURL.getValue())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Response<PostList>>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onNext(#NonNull Response<PostList> postListResponse) {
if (postListResponse.isSuccessful()) {
if (postListResponse.body() != null
&& postListResponse.body().getNextPageToken() != null) {
Log.e(TAG, postListResponse.body().getNextPageToken());
token.setValue(postListResponse.body().getNextPageToken());
isLoading.setValue(false);
}
postListMutableLiveData.setValue(postListResponse.body());
for (int i = 0; i < postListResponse.body().getItems().size(); i++) {
repository.localDataSource.insertItem(postListResponse.body()
.getItems().get(i))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onComplete() {
}
#Override
public void onError(#NonNull Throwable e) {
}
});
}
finalURL.setValue(finalURL.getValue() + "&pageToken=" + token.getValue());
} else {
isLoading.setValue(false);
errorCode.setValue(postListResponse.code());
Log.e(TAG, "onNext: " + postListResponse.code());
Log.e(TAG, "onNext: " + postListResponse.errorBody());
}
}
#Override
public void onError(#NonNull Throwable e) {
isLoading.setValue(false);
Log.e(TAG, e.getMessage() + e.getCause());
// ifAnythingWrongHappened.setValue(true);
if (e instanceof HttpException) {
errorCode.setValue(((HttpException) e).code());
}
}
#Override
public void onComplete() {
}
});
}
public void getPostListByLabel() {
isLoading.setValue(true);
Log.e(TAG, finalURL.getValue());
repository.remoteDataSource.getPostListByLabel(finalURL.getValue())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Response<com.blogspot.abtallaldigital.pojo.PostList>>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onNext(#NonNull Response<com.blogspot.abtallaldigital.pojo.PostList> postListResponse) {
if (postListResponse.isSuccessful()) {
if (postListResponse.body() != null) {
// Log.e(TAG, postListResponse.body().getNextPageToken());
token.setValue(postListResponse.body().getNextPageToken());
}
postListMutableLiveData.setValue(postListResponse.body());
isLoading.setValue(false);
finalURL.postValue(Constants.getBaseUrlPostsByLabel()
+ "posts?labels=" + label.getValue() + "&pageToken="
+ token.getValue()
+ "&key=" + Constants.getKEY());
} else {
isLoading.setValue(false);
errorCode.setValue(postListResponse.code());
Log.e(TAG, "onNext: " + postListResponse.code());
Log.e(TAG, "onNext: " + postListResponse.errorBody());
}
}
#Override
public void onError(#NonNull Throwable e) {
isLoading.setValue(false);
Log.e(TAG, e.getMessage() + e.getCause());
if (e instanceof HttpException) {
errorCode.setValue(((HttpException) e).code());
}
}
#Override
public void onComplete() {
}
});
}
public void getItemsBySearch(String keyword) {
isLoading.setValue(true);
searchError.setValue(false);
String url = Constants.getBaseUrl() +
"search?q=" + keyword + "&key=" + Constants.getKEY();
Log.e(TAG, "getItemsBySearch: " + url);
repository.remoteDataSource.getPostListBySearch(url)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Response<com.blogspot.abtallaldigital.pojo.PostList>>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onNext(#NonNull Response<PostList> postListResponse) {
if (postListResponse.isSuccessful()) {
if (postListResponse.body() != null
&& postListResponse.body().getNextPageToken() != null) {
Log.e(TAG, postListResponse.body().getNextPageToken());
token.setValue(postListResponse.body().getNextPageToken());
isLoading.setValue(false);
}
postListMutableLiveData.setValue(postListResponse.body());
} else {
isLoading.setValue(false);
searchError.setValue(true);
Log.e(TAG, "onNext: list is null");
}
}
#Override
public void onError(#NonNull Throwable e) {
isLoading.setValue(false);
Log.e(TAG, e.getMessage() + e.getCause());
// ifAnythingWrongHappened.setValue(true);
if (e instanceof HttpException) {
errorCode.setValue(((HttpException) e).code());
}
}
#Override
public void onComplete() {
}
});
}
public void getItemsBySearchInDB(String keyword) {
Log.d(TAG, "getItemsBySearchInDB: called");
repository.localDataSource.getItemsBySearch(keyword)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<com.blogspot.abtallaldigital.pojo.Item>>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onNext(#NonNull List<Item> items) {
if (items.isEmpty()) {
searchError.setValue(true);
Log.e(TAG, "onNext: list is empty");
} else {
getItemsBySearchMT.setValue(items);
Log.d(TAG, "onNext: " + items.size());
}
}
#Override
public void onError(#NonNull Throwable e) {
searchError.setValue(true);
}
#Override
public void onComplete() {
}
});
}
public void insertFavorites(FavoritesEntity favoritesEntity) {
repository.localDataSource.insertFavorites(favoritesEntity)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onComplete() {
}
#Override
public void onError(#NonNull Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
});
}
public LiveData<List<FavoritesEntity>> getAllFavorites() {
return repository.localDataSource.getAllFavorites();
}
public void deleteFavoritePost(FavoritesEntity favoritesEntity) {
repository.localDataSource.deleteFavorite(favoritesEntity);
}
public void deleteAllFavorites() {
repository.localDataSource.deleteAllFavorites()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onComplete() {
}
#Override
public void onError(#NonNull Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
});
}
}
Try initializing the adapter in onCreate instead of onViewCreated
Then you can set the adapter on recyclerview in onViewCreated.
Also use try using LiveData Event Wrapper :
https://stackoverflow.com/a/51762972/9854554
LiveData Event Wrapper in Java : https://stackoverflow.com/a/56072658
It will prevent livedata observer from getting data again on fragment resume (when we subscribe again on the livedata)
you are set recycler view data in onViewCreated which called everytime,
i recommend viewmodel for better lifecycle handing, use LiveData or StateFlow in viewModel to prove your data integrity

Work Manager: How to return result only when network request is done

This is my worker class and I have tried it but doesn't seem to work the way I want it to. I only want to return the result of doWork() only when the PUT request is done. Any help would be appreciated, thanks.
public class MyWorker extends Worker {
private Context context;
public MyWorker(
#NonNull Context context,
#NonNull WorkerParameters params) {
super(context, params);
this.context = context;
}
#NonNull
#Override
public Result doWork() {
return putData();
}
private Result putData() {
final Result[] result = new Result[1];
String url = "https://www.myurl.com";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.PUT, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if(response == null)
result[0] = Result.retry();
else
result[0] = Result.success();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
result[0] = Result.retry();
} else if (error instanceof AuthFailureError) {
//TODO
} else if (error instanceof ServerError) {
//TODO
result[0] = Result.retry();
} else if (error instanceof NetworkError) {
//TODO
result[0] = Result.retry();
} else if (error instanceof ParseError) {
//TODO
}
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return params;
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
return super.getParams();
}
};
VolleyHelper.getInstance(context).addToRequestQueue(jsonObjectRequest);
return result[0];
}
}
Thanks to #pfmaggi I was able to do this
interface MyCallback{
void onSuccess();
void onError();
}
public class MyWorker extends ListenableWorker {
private Context context;
public MyWorker(
#NonNull Context context,
#NonNull WorkerParameters params) {
super(context, params);
this.context = context;
}
#NonNull
#Override
public ListenableFuture<Result> startWork() {
return CallbackToFutureAdapter.getFuture(completer -> {
MyCallback callback = new MyCallback() {
#Override
public void onSuccess() {
completer.set(Result.success());
}
#Override
public void onError() {
completer.set(Result.retry());
}
};
putData(callback);
return callback;
});
}
private void putData(MyCallback callback) {
String url = "https://www.myurl.com";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.PUT, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if(response == null)
callback.onError();
else
callback.onSuccess();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
callback.onError();
} else if (error instanceof AuthFailureError) {
//TODO
} else if (error instanceof ServerError) {
//TODO
callback.onError();
} else if (error instanceof NetworkError) {
//TODO
callback.onError();
} else if (error instanceof ParseError) {
//TODO
}
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return params;
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
return super.getParams();
}
};
VolleyHelper.getInstance(context).addToRequestQueue(jsonObjectRequest);
}
}

RxJava filter operator

I am new in rxJava.
Well, I was testing few examples to integrate operators in rxJava.
So, I have a problem with this:
Observable.just("JUAN", "LUCILA", "ARMANDO").map(new Function<String, Integer>() {
#Override
public Integer apply(String s) throws Exception {
return s.length();
}
}).all(new Predicate<Integer>() {
#Override
public boolean test(Integer integer) throws Exception {
return integer > 0;
}
}).filter(new Predicate<Boolean>() {
#Override
public boolean test(Boolean aBoolean) throws Exception {
return aBoolean;
}
}).subscribe(new Observer<Boolean>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Boolean value) {
Log.d("STATUS: ", "OK");
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
Log.d("STATUS: ", "COMPLETE");
}
})
So, AndroidStudio marks me error on subscribe(new Observer).
My objective is transform the names to a number by the length, so with all I hope make a condition, obviously it will be true, and late, filter that TRUE, from filter, and next show me a log message saying OK!
I hope that you can help me!
Thanks!
Check Single at http://reactivex.io/RxJava/2.x/javadoc/
As said in the comment Observable.all(...) you have type Single then from Single.filter(...) you have type Maybe.
So use you need toObservable() and then subscribe.
#CheckReturnValue
#SchedulerSupport(SchedulerSupport.NONE)
public final Maybe<T> filter(Predicate<? super T> predicate) {
ObjectHelper.requireNonNull(predicate, "predicate is null");
return RxJavaPlugins.onAssembly(new MaybeFilterSingle<T>(this, predicate));
}
`
Change to
Observable.just("JUAN", "LUCILA", "ARMANDO").map(new Function<String, Integer>() {
#Override
public Integer apply(String s) throws Exception {
return s.length();
}
}).all(new Predicate<Integer>() {
#Override
public boolean test(Integer integer) throws Exception {
return integer > 0;
}
}).filter(new Predicate<Boolean>() {
#Override
public boolean test(Boolean aBoolean) throws Exception {
return aBoolean;
}
}).toObservable().subscribe(new Observer<Boolean>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Boolean value) {
Log.d("STATUS: ", "OK");
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
Log.d("STATUS: ", "COMPLETE");
}
});

RxJava2/RxAndroid Fetching information from website issue

I'm trying to explore Rxjava 2 and get some issue with fetching information from website. Actutally Observer give me an error.
My code:
observable.subscribe(getObserver());
Observable
Observable<String> observable = Observable.fromCallable(new Callable<String>() {
#Override
public String call() throws Exception {
String data = getHeadlines(SOURCE_WEB);
return data;
}
});
Observer
protected <String> Observer<String> getObserver() {
return new Observer<String>() {
#Override
public void onSubscribe(Disposable d) {
Log.i("Observer get: ", "mamy sub");
Toast.makeText(context, "Wait...", Toast.LENGTH_SHORT).show();
}
#Override
public void onNext(String value) {
Log.i("Observer get: ",value.toString());
}
#Override
public void onError(Throwable e) {
Log.i("Observer get ", "Error");
}
#Override
public void onComplete() {
Log.i("Observer ", "complete");
}
};
}
My fetching method
public String getHeadlines(String source) throws IOException {
Document doc = (Document) Jsoup.connect(source).get();
Elements newsHeadlines = doc.select("h2");
return newsHeadlines.toString();
}
When I'm using AsyncTask everything work fine...

Can I parallelise an operation driven by a flatMap?

Say I have a method like the code below, in which a List is flatMapped to individual strings, each of which has some expensive operation applied to them. Is there any way to parallelise the expensive operations, in the same way that I'd use parallelStream() in Java 8?
final List<String> names = new ArrayList<String>() {{
add("Ringo");
add("John");
add("Paul");
add("George");
}};
Observable.just(names).subscribeOn(Schedulers.io())
.flatMap(new Func1<List<String>, Observable<String>>() {
#Override
public Observable<String> call(final List<String> names) {
return Observable.create(new Observable.OnSubscribe<String>() {
#Override
public void call(Subscriber<? super String> subscriber) {
for (String name : names) {
subscriber.onNext(name);
}
}
});
}
})
.map(new Func1<String, String>() {
#Override
public String call(String s) {
//Simulate expensive operation
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return s.toUpperCase();
}
}).subscribe(new Subscriber<String>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(String s) {
Log.v("RXExample", s + " on " + Thread.currentThread().getName());
}
});
For completion, applying the change recommended in the answer looks like the following and works nicely!
final List<String> names = new ArrayList<String>() {{
add("Ringo");
add("John");
add("Paul");
add("George");
}};
Observable.just(names).subscribeOn(Schedulers.io())
.flatMap(new Func1<List<String>, Observable<String>>() {
#Override
public Observable<String> call(final List<String> names) {
return Observable.create(new Observable.OnSubscribe<String>() {
#Override
public void call(final Subscriber<? super String> subscriber) {
for (final String name : names) {
Observable
.just(name)
.subscribeOn(Schedulers.from(Executors.newFixedThreadPool(5)))
.map(new Func1<String, String>() {
#Override
public String call(String s) {
//Simulate expensive operation
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return s.toUpperCase();
}
}).subscribe(new Observer<String>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(String s) {
subscriber.onNext(name);
}
});
}
}
});
}
})
.subscribe(new Subscriber<String>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(String s) {
Log.v("RXExample", s + " on " + Thread.currentThread().getName());
}
});
you can parallelise work with flatMap as in the following example. I am using RxJava2 for testing.
For further explanation please read the flatMap usage from here: http://tomstechnicalblog.blogspot.de/2015/11/rxjava-achieving-parallelization.html
#Test
public void name() throws Exception {
final List<String> names = new ArrayList<String>() {{
add("Ringo");
add("John");
add("Paul");
add("George");
}};
Observable<String> stringObservable = Observable.fromIterable(names)
.flatMap(s -> {
return longWork(s).doOnNext(s1 -> {
printCurrentThread(s1);
}).subscribeOn(Schedulers.newThread());
});
TestObserver<String> test = stringObservable.test();
test.awaitDone(2_000, TimeUnit.MILLISECONDS).assertValueCount(4);
}
private Observable<String> longWork(String s) throws InterruptedException {
return Observable.fromCallable(() -> {
Thread.sleep(1_000);
return s;
});
}
private void printCurrentThread(String additional) {
System.out.println(additional + "_" + Thread.currentThread());
}

Categories