I am using MVVM pattern in which I am using SwipeRefresh layout to refresh recycler view in my layout.When I am pulling it then it continue to refresh even after method completed successfully.
Below is my code:
MainActivity.java
refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
userRepository.getUserList();
}
});
UserRepository.java
public void getUserList(){
Retrofit retrofit = RetrofitClient.getInstance();
ApiService apiService = retrofit.create(ApiService.class);
Call<List<User>> userList = apiService.getUser();
userList.enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, final Response<List<User>> response) {
Completable.fromAction(new Action() {
#Override
public void run() throws Exception {
if(response.body() != null) {
List<User> list = response.body();
for (int i = 0; i < list.size(); i++) {
String id = list.get(i).get_id();
String names = list.get(i).getName();
String age = list.get(i).getAge();
User user = new User(id,names,age);
userDb.userDao().Insert(user);
}
}
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onComplete() {
Toast.makeText(context,"Data inserted",Toast.LENGTH_SHORT).show();
}
#Override
public void onError(Throwable e) {
Toast.makeText(context,e.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
Toast.makeText(context,t.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
Method fetching list is in another class UserRepository and I am calling method in another activity MainActivity.I am not getting any way how can I stop refreshing process.Someone please let me know a way to stop refreshing process.
Any help would be appreciated.
THANKS
To disable the progress dialog add this,
swipeLayout.setRefreshing(false);
Related
i want to call api request every x second using Runnable and read live response to multiple fragment on every api call.
i try bellow code but if start runnable from FragmentA then can't get response on FragmentB even if runnable already run api call in background.
when i run RunnableDemo(mContext, this, JsonRpc.Method.TELL_ACTIVE).run(); in fragmentA and start runnable however can get onDataSuccess in fragmentB.
and if i use RunnableDemo(mContext, this, JsonRpc.Method.TELL_ACTIVE).run(); in FragmentB then run two time API call for FragmentA and FragmentB.
so, how can i run api call every x second once and receive response on multiple fragments?
thank you,
RunnableDemo.java
public class RunnableDemo implements Runnable{
RunnableDemo.RunnableDemoListener listener;
public void run() {
if (myRunnable == null) {
myHandler.postDelayed(myRunnable = new Runnable() {
public void run() {
if(shouldRun) {
running = true;
//do something
loop();
}
myHandler.postDelayed(myRunnable, updateInterval);
}
}, updateInterval);
}
}
private void loop() {
...retrofit....
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NonNull Call<ResponseBody> call, #NonNull Response<ResponseBody> response)
{
listener.onDataSuccess(response);
}
#Override
public void onFailure(#NonNull Call<ResponseBody> call, #NonNull Throwable t)
{
listener.onDataError("error");
}
});
}
public void stop() {
if (listener != null) {
listener.onStopped();
}
running = false;
shouldRun = false;
}
public final boolean isRunning() {
return running;
}
public final boolean safeStop() {
if (listener != null) {
listener.onStopped();
}
shouldRun = false;
running = false;
return true;
}
// Listener defined earlier
public interface RunnableDemoListener {
public void onDataError(String title);
public void onDataSuccess(Response<ResponseBody> responseBody);
public void onStopped();
}
}
FragmentA.java
public class FargmentA extends Fragment implements RunnableDemo.RunnableDemoListener{
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
RunnableDemo runnableDemo = new RunnableDemo(mContext, this, JsonRpc.Method.TELL_ACTIVE);
if(!runnableDemo.isRunning()) {
runnableDemo.run();
}
}
#Override
public void onDataError(String title) {
Log.i("TEST", "TestRunnable onResponse receive error Files: "+ title);
}
#Override
public void onDataSuccess(Response<ResponseBody> responseBody) {
Log.i("TEST", "TestRunnable onResponse receive success Files: "+ responseBody.code());
}
#Override
public void onStopped() {
Log.i("TEST", "TestRunnable onResponse receive onStopped Files: ");
}
}
FragmentB.java
public class FargmentB extends Fragment implements RunnableDemo.RunnableDemoListener{
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
RunnableDemo runnableDemo = new RunnableDemo(mContext, this, JsonRpc.Method.TELL_ACTIVE);
if(!runnableDemo.isRunning()) {
runnableDemo.run();
}
}
#Override
public void onDataError(String title) {
Log.i("TEST", "TestRunnable onResponse receive error Files: "+ title);
}
#Override
public void onDataSuccess(Response<ResponseBody> responseBody) {
Log.i("TEST", "TestRunnable onResponse receive success Files: "+ responseBody.code());
}
#Override
public void onStopped() {
Log.i("TEST", "TestRunnable onResponse receive onStopped Files: ");
}
}
I am trying out this simple program where I try to send a POST request to the server and fetch the response and store them into the spinner. This is my code;
fetchcolonynames("code"); //sending POST request
if (spin1 != null) {
//spin.setAdapter(adapter) doesn't work here
spin1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
spin1.setAdapter(adapter); //doesn't work spinner shows nothing on clicked
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
This is my fetchcolonynames() method:
private void fetchcolonynames(String input){
call=api.fetchcolonynames(input);
if(call!=null){
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.body() != null) {
JSONArray array = null;
try {
array = new JSONArray(response.body());
for(int i=0;i<array.length();i++){
arr.add(array.getString(i));
}
} catch (JSONException e) {
e.printStackTrace();
}
Collections.sort(arr); //data is correct here
adapter = new ArrayAdapter<String>(view.getContext(), android.R.layout.simple_spinner_item,arr);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
}
All my variables are globally declared. I want to populate the spinner, when the user clicks it. How do I accomplish this?
#Dao
public interface LibraryCoverContentDao {
#Query("SELECT * FROM LibraryCoverContent where rush_id = :rush_id")
LiveData<List<LibraryCoverContent>> getContentsFromRushID(String rush_id);
#Query("DELETE FROM library_cover where rush_id = :rush_id")
void deleteContentsFromRushID(String rush_id);
#Insert(onConflict = REPLACE)
void insertCoverContents(LibraryCoverContent... contents);
}
I want to open another activity once a list LiveData> mLibraryCoverContents is not null.
I am inserting the items downloaded from a retrofit call one by one into the room database, so apparently, my startActivity() call for the next activity happens many a times and multiple-same activities are opened over this activity.
I want only a single activity on top by calling onChanged only after all items of the retrofit call are inserted into db.
Please see the following related code for reference:
public void openReadRushScreen(final int index) {
int count = mCoversList.size();
if(count > index){
mRushIDContent = mLibraryContentRepository.getContentsFromID(mCoversList.get(index).getRush_id());
mRushIDContent.observe(this, new Observer<List<LibraryCoverContent>>() {
#Override
public void onChanged(#Nullable List<LibraryCoverContent> libraryCoverContents) {
Toast.makeText(getActivity(), "ON CHANGED", Toast.LENGTH_SHORT).show();
if(libraryCoverContents!=null && libraryCoverContents.size()>0){
mRushIDContentsList = libraryCoverContents;
if(mRushIDContentsList.size()>0 && mRushIDContentsList.get(0).getRush_id().equals(mCoversList.get(index).getRush_id())){
mRushIDContentsList = new ArrayList<>();
startActivity(ReadRushActivity.getStartIntent(getActivity(), mCoversList.get(index).getRush_id(),
mCoversList.get(index).isRush_audio(),
mCoversList.get(index).getTitle()));
}
}
else {
if(mCoversList!=null && mCoversList.size()>index) getContent(mCoversList.get(index).getRush_id());
}
}
});
}
else Toast.makeText(getActivity(), "Empty Cover", Toast.LENGTH_SHORT).show();
}
public void getContent(String mRushId) {
mApiService = ApiClient.getClient().create(ApiInterface.class);
Call<List<Content>> call = mApiService.getRushContent(mRushId);
if(call!=null){
call.enqueue(new Callback<List<Content>>() {
#Override
public void onResponse(#NonNull Call<List<Content>> call, #NonNull Response<List<Content>> response) {
mContents = response.body();
if(mContents!=null && mContents.size()>0){
//noinspection ConstantConditions
List<LibraryCoverContent> coverContent = new ArrayList<>();
for(int i=0; i<mContents.size(); i++){
coverContent.add(new LibraryCoverContent
(mContents.get(i).getContent_id(), mContents.get(i).getRush_id(),
mContents.get(i).getContent(), mContents.get(i).getAttr(),
mContents.get(i).getDatetime(), mContents.get(i).getPage_no()));
}
mLibraryContentRepository.insertContentItems(coverContent);
}
}
#Override
public void onFailure(#NonNull Call<List<Content>> call, #NonNull Throwable t) {
// if(getActivity()!=null) Toast.makeText(getActivity(), "Network Error while downloading rush content", Toast.LENGTH_LONG).show();
}
});
}
}
#SuppressLint("StaticFieldLeak")
public void insertContentItems(final List<LibraryCoverContent> items) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
for(int i=0; i<items.size(); i++){
mLibraryCoverContentDao.insertCoverContents(items.get(i));
}
return null;
}
}.execute();
}
i'm making unit test for my application
my unit test class has this method
#Before
public void initialize() {
mContext = InstrumentationRegistry.getTargetContext();
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(mContext).name("realmTest").inMemory().build();
Realm.setDefaultConfiguration(realmConfiguration);
mWorkoutsModel = new WorkoutsModel(mContext);
mRealm = Realm.getInstance(realmConfiguration);
mWorkoutsModel.registerListener(this);
}
#Test
public void getWorkouts() throws Exception {
mWorkoutsModel.onStart();
mLock.await();
mWorkoutsModel.onStop();
}
#After
public void deInitialize() {
mWorkoutsModel.unRegisterListener();
mRealm.close();
}
and my model
#Override
public void onStart() {
mRealm = Realm.getDefaultInstance();
getDataFromApi();
}
private boolean getDataFromApi() {
Constants.AllAPIs.ALLWorkouts allWorkouts = new Constants.AllAPIs.ALLWorkouts();
if (Permissions.isInternetConnectionExist(mContext)) {
mApiHandler.downLoadDataFromApi(AllWorkouts.class, allWorkouts.getBaseUrl(),
new APIHandler.StringResponseHandler<AllWorkouts>() {
#Override
public void onResponse(AllWorkouts response) {
insertWorkouts(response.getWorkouts());
},
new APIHandler.ErrorResponseHandler() {
#Override
public void onErrorResponse(VolleyError error) {
}
}, TAG);
return true;
} else {
return false;
}
}
private void insertWorkouts(final List<Workout> workouts) {
mCurrentInsertTransaction = mRealm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm bgRealm) {
bgRealm.copyToRealmOrUpdate(workouts);
}
}, new Realm.Transaction.OnSuccess() {
#Override
public void onSuccess() {
}
});
}
my problem that the unittest calls onStart which create realm object in the model in test thread but volley force onResponse to run on UIThread which makes realm throw exception Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
the code runs perfect in normal, but in test it fails
does anyone faced same problem or can solve it ?
i solved my problem by run the test in handler
new Handler(mContext.getMainLooper()).post(new Runnable() {
#Override
public void run() {
try {
mWorkoutsModel.onStart();
mLock.await();
mWorkoutsModel.onStop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
hope that help somebody
I have something like that:
public void function sendPhotosAndSave (ArrayList<Photo> photos) {
// Iterate through all photos
// Send a POST request using volley for each photo
// Alert when all photos sended
// ????
.subscribe(new Subscriber<Boolean>() {
#Override
public void onCompleted() {
// Save
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(Boolean aBoolean) {
}
});
}
I need to send all photos (Multipart/POST) and then send a save request.
How do i iterate the photos requests using RxJava and known when it's done?
You can do something like this:
public void sendPhotosAndSave(List<Photo> photos) {
Observable.from(photos)
.flatMap(photo -> sendRequest(photo).subscribeOn(Schedulers.io()))
.subscribe(new Subscriber<Boolean>() {
#Override
public void onCompleted() {
// Save
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(Boolean aBoolean) {
}
});
}
private Observable<Boolean> sendRequest(Photo photo) {
return Observable.just(/*your request logic*/);
}