Add loading view to show sync progress

This commit is contained in:
Shinokuni 2019-03-13 15:04:07 +01:00
parent fc369888ac
commit 5689fef568
7 changed files with 118 additions and 17 deletions

View File

@ -1,8 +1,8 @@
package com.readrops.app.activities;
import android.app.Dialog;
import android.arch.lifecycle.ViewModelProvider;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -20,6 +20,9 @@ import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
@ -28,8 +31,6 @@ import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader;
import com.bumptech.glide.util.ViewPreloadSizeProvider;
import com.github.clans.fab.FloatingActionMenu;
import com.readrops.app.database.entities.Feed;
import com.readrops.app.utils.SyncError;
import com.readrops.app.views.AddFeedDialog;
import com.readrops.app.views.MainItemListAdapter;
import com.readrops.app.viewmodels.MainViewModel;
import com.readrops.app.R;
@ -46,10 +47,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import io.reactivex.Observer;
import io.reactivex.SingleObserver;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.observers.DisposableCompletableObserver;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers;
public class MainActivity extends AppCompatActivity implements SimpleCallback, SwipeRefreshLayout.OnRefreshListener {
@ -70,7 +72,12 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
private MainViewModel viewModel;
private RelativeLayout syncProgressLayout;
private TextView syncProgress;
private ProgressBar syncProgressBar;
private int feedCount;
private int feedNb;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -102,7 +109,7 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
return true;
});
viewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication()).create(MainViewModel.class);
viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
viewModel.setSimpleCallback(this);
itemsMap = new TreeMap<>(LocalDateTime::compareTo);
@ -118,6 +125,12 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
refreshLayout = findViewById(R.id.swipe_refresh_layout);
refreshLayout.setOnRefreshListener(this);
syncProgressLayout = findViewById(R.id.sync_progress_layout);
syncProgress = findViewById(R.id.sync_progress_text_view);
syncProgressBar = findViewById(R.id.sync_progress_bar);
feedCount = 0;
initRecyclerView();
}
@ -221,7 +234,30 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
public void onRefresh() {
Log.d(TAG, "syncing started");
sync(null);
viewModel.getFeedCount()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<Integer>() {
@Override
public void onSubscribe(Disposable d) {
syncProgressLayout.setVisibility(View.VISIBLE);
syncProgressBar.setProgress(0);
}
@Override
public void onSuccess(Integer integer) {
feedNb = integer;
sync(null);
}
@Override
public void onError(Throwable e) {
Toast.makeText(getApplicationContext(), "error on getting feeds number", Toast.LENGTH_LONG).show();
}
});
}
public void displayAddFeedDialog(View view) {
@ -262,16 +298,21 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
viewModel.sync(feeds)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<List<SyncError>>() {
.subscribe(new Observer<Feed>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(List<SyncError> syncErrors) {
refreshLayout.setRefreshing(false);
adapter.submitList(newItems);
public void onNext(Feed feed) {
syncProgress.setText(getString(R.string.updating_feed, feed.getName()));
feedCount++;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
syncProgressBar.setProgress((feedCount * 100) / feedNb, true);
} else
syncProgressBar.setProgress((feedCount * 100) / feedNb);
}
@Override
@ -279,6 +320,14 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
refreshLayout.setRefreshing(false);
Toast.makeText(getApplication(), e.getMessage(), Toast.LENGTH_LONG).show();
}
@Override
public void onComplete() {
syncProgressBar.setProgress(0);
syncProgressLayout.setVisibility(View.GONE);
refreshLayout.setRefreshing(false);
adapter.submitList(newItems);
}
});
}
}

View File

@ -17,6 +17,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Single;
public abstract class ARepository {
@ -35,7 +36,7 @@ public abstract class ARepository {
this.callback = callback;
}
public abstract Single<List<SyncError>> sync(List<Feed> feeds);
public abstract Observable<Feed> sync(List<Feed> feeds);
public abstract void addFeed(ParsingResult result);
@ -64,6 +65,12 @@ public abstract class ARepository {
}
public Single<Integer> getFeedCount() {
return Single.create(emitter -> {
emitter.onSuccess(database.feedDao().getFeedCount());
});
}
protected void failureCallBackInMainThread(Exception e) {
Handler handler = new Handler(Looper.getMainLooper());

View File

@ -39,6 +39,7 @@ import java.util.List;
import java.util.TreeMap;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Single;
public class LocalFeedRepository extends ARepository implements QueryCallback {
@ -58,8 +59,8 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
}
@Override
public Single<List<SyncError>> sync(List<Feed> feeds) {
return Single.create(emitter -> {
public Observable<Feed> sync(List<Feed> feeds) {
return Observable.create(emitter -> {
List<Feed> feedList;
if (feeds == null || feeds.size() == 0)
@ -71,6 +72,7 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
List<SyncError> syncErrors = new ArrayList<>();
for (Feed feed : feedList) {
emitter.onNext(feed);
SyncError syncError = new SyncError();
try {
@ -105,7 +107,7 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
}
}
emitter.onSuccess(syncErrors);
emitter.onComplete();
});
}

View File

@ -15,6 +15,7 @@ import com.readrops.app.utils.ParsingResult;
import java.util.List;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Single;
public class MainViewModel extends AndroidViewModel {
@ -38,11 +39,15 @@ public class MainViewModel extends AndroidViewModel {
repository.setCallback(simpleCallback);
}
public Single<List<SyncError>> sync(List<Feed> feeds) {
public Observable<Feed> sync(List<Feed> feeds) {
return repository.sync(feeds);
}
public void addFeed(ParsingResult parsingResult) {
repository.addFeed(parsingResult);
}
public Single<Integer> getFeedCount() {
return repository.getFeedCount();
}
}

View File

@ -10,6 +10,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
@ -26,6 +27,40 @@
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:id="@+id/sync_progress_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="visible">
<RelativeLayout
android:id="@+id/sync_progress_feeds_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:padding="8dp">
<TextView
android:id="@+id/sync_progress_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@color/colorBackground"
tools:text="updating feeds" />
</RelativeLayout>
<ProgressBar
android:id="@+id/sync_progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/sync_progress_feeds_layout"
android:max="100"/>
</RelativeLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
@ -44,7 +79,8 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<com.github.clans.fab.FloatingActionMenu
android:id="@+id/fab_menu"

View File

@ -31,5 +31,6 @@
<string name="cancel">Retour</string>
<string name="delete_feed">Supprimer le flux ?</string>
<string name="load">Charger</string>
<string name="updating_feed">Mise à jour du flux : %1$s</string>
</resources>

View File

@ -33,4 +33,5 @@
<string name="cancel">Cancel</string>
<string name="delete_feed">Delete feed ?</string>
<string name="load">Load</string>
<string name="updating_feed">Updating feed : %1$s</string>
</resources>