Skip to content

Commit

Permalink
Replaced Icepick with Bridge and Android-State
Browse files Browse the repository at this point in the history
* IcePick fails on Java 21 (default in Android Studio 2024.2)
* Bridge is the most modern alternative that is currently available. It is backed by ``Android-State`` and can be configured with various frameworks
* In the long term this should be replaced with something better
  • Loading branch information
litetex authored and Stypox committed Nov 10, 2024
1 parent 5bd4ed7 commit 8ada566
Show file tree
Hide file tree
Showing 30 changed files with 167 additions and 100 deletions.
7 changes: 4 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ ext {
androidxRoomVersion = '2.6.1'
androidxWorkVersion = '2.8.1'

icepickVersion = '3.2.0'
stateSaverVersion = '1.4.1'
exoPlayerVersion = '2.18.7'
googleAutoServiceVersion = '1.1.1'
groupieVersion = '2.10.1'
Expand Down Expand Up @@ -243,8 +243,9 @@ dependencies {

/** Third-party libraries **/
// Instance state boilerplate elimination
implementation "frankiesardo:icepick:${icepickVersion}"
kapt "frankiesardo:icepick-processor:${icepickVersion}"
implementation 'com.github.livefront:bridge:v2.0.2'
implementation "com.evernote:android-state:$stateSaverVersion"
kapt "com.evernote:android-state-processor:$stateSaverVersion"

// HTML parser
implementation "org.jsoup:jsoup:1.17.2"
Expand Down
9 changes: 0 additions & 9 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@
## Rules for ExoPlayer
-keep class com.google.android.exoplayer2.** { *; }

## Rules for Icepick. Copy pasted from https://github.com/frankiesardo/icepick
-dontwarn icepick.**
-keep class icepick.** { *; }
-keep class **$$Icepick { *; }
-keepclasseswithmembernames class * {
@icepick.* <fields>;
}
-keepnames class * { @icepick.State *;}

## Rules for OkHttp. Copy pasted from https://github.com/square/okhttp
-dontwarn okhttp3.**
-dontwarn okio.**
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/schabi/newpipe/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.schabi.newpipe.extractor.downloader.Downloader;
import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.settings.NewPipeSettings;
import org.schabi.newpipe.util.BridgeStateSaverInitializer;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.StateSaver;
Expand Down Expand Up @@ -107,6 +108,7 @@ public void onCreate() {
Localization.getPreferredContentCountry(this));
Localization.initPrettyTime(Localization.resolvePrettyTime(getApplicationContext()));

BridgeStateSaverInitializer.init(this);
StateSaver.init(this);
initNotificationChannels();

Expand Down
9 changes: 5 additions & 4 deletions app/src/main/java/org/schabi/newpipe/BaseFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import icepick.Icepick;
import icepick.State;
import com.evernote.android.state.State;
import com.livefront.bridge.Bridge;


public abstract class BaseFragment extends Fragment {
protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
Expand Down Expand Up @@ -48,7 +49,7 @@ public void onCreate(final Bundle savedInstanceState) {
+ "savedInstanceState = [" + savedInstanceState + "]");
}
super.onCreate(savedInstanceState);
Icepick.restoreInstanceState(this, savedInstanceState);
Bridge.restoreInstanceState(this, savedInstanceState);
if (savedInstanceState != null) {
onRestoreInstanceState(savedInstanceState);
}
Expand All @@ -70,7 +71,7 @@ public void onViewCreated(@NonNull final View rootView, final Bundle savedInstan
@Override
public void onSaveInstanceState(@NonNull final Bundle outState) {
super.onSaveInstanceState(outState);
Icepick.saveInstanceState(this, outState);
Bridge.saveInstanceState(this, outState);
}

protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
Expand Down
9 changes: 5 additions & 4 deletions app/src/main/java/org/schabi/newpipe/RouterActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceManager;

import com.evernote.android.state.State;
import com.livefront.bridge.Bridge;

import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.databinding.ListRadioIconItemBinding;
import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding;
Expand Down Expand Up @@ -98,8 +101,6 @@
import java.util.Optional;
import java.util.function.Consumer;

import icepick.Icepick;
import icepick.State;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.Single;
Expand Down Expand Up @@ -152,7 +153,7 @@ protected void onCreate(final Bundle savedInstanceState) {
getWindow().setAttributes(params);

super.onCreate(savedInstanceState);
Icepick.restoreInstanceState(this, savedInstanceState);
Bridge.restoreInstanceState(this, savedInstanceState);

// FragmentManager will take care to recreate (Playlist|Download)Dialog when screen rotates
// We used to .setOnDismissListener(dialog -> finish()); when creating these DialogFragments
Expand Down Expand Up @@ -197,7 +198,7 @@ protected void onStop() {
@Override
protected void onSaveInstanceState(@NonNull final Bundle outState) {
super.onSaveInstanceState(outState);
Icepick.saveInstanceState(this, outState);
Bridge.saveInstanceState(this, outState);
}

@Override
Expand Down
8 changes: 6 additions & 2 deletions app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,12 @@ class AboutActivity : AppCompatActivity() {
"https://github.com/lisawray/groupie", StandardLicenses.MIT
),
SoftwareComponent(
"Icepick", "2015", "Frankie Sardo",
"https://github.com/frankiesardo/icepick", StandardLicenses.EPL1
"Android-State", "2018", "Evernote",
"https://github.com/Evernote/android-state", StandardLicenses.EPL1
),
SoftwareComponent(
"Bridge", "2021", "Livefront",
"https://github.com/livefront/bridge", StandardLicenses.APACHE2
),
SoftwareComponent(
"Jsoup", "2009 - 2020", "Jonathan Hedley",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import androidx.fragment.app.DialogFragment;
import androidx.preference.PreferenceManager;

import com.evernote.android.state.State;
import com.livefront.bridge.Bridge;
import com.nononsenseapps.filepicker.Utils;

import org.schabi.newpipe.MainActivity;
Expand All @@ -59,6 +61,8 @@
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard;
import org.schabi.newpipe.streams.io.StoredDirectoryHelper;
import org.schabi.newpipe.streams.io.StoredFileHelper;
import org.schabi.newpipe.util.AudioTrackAdapter;
import org.schabi.newpipe.util.AudioTrackAdapter.AudioTracksWrapper;
import org.schabi.newpipe.util.FilePickerActivityHelper;
import org.schabi.newpipe.util.FilenameUtils;
import org.schabi.newpipe.util.ListHelper;
Expand All @@ -67,8 +71,6 @@
import org.schabi.newpipe.util.SimpleOnSeekBarChangeListener;
import org.schabi.newpipe.util.StreamItemAdapter;
import org.schabi.newpipe.util.StreamItemAdapter.StreamInfoWrapper;
import org.schabi.newpipe.util.AudioTrackAdapter;
import org.schabi.newpipe.util.AudioTrackAdapter.AudioTracksWrapper;
import org.schabi.newpipe.util.ThemeHelper;

import java.io.File;
Expand All @@ -79,8 +81,6 @@
import java.util.Objects;
import java.util.Optional;

import icepick.Icepick;
import icepick.State;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import us.shandian.giga.get.MissionRecoveryInfo;
import us.shandian.giga.postprocessing.Postprocessing;
Expand Down Expand Up @@ -214,7 +214,7 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
context = getContext();

setStyle(STYLE_NO_TITLE, ThemeHelper.getDialogTheme(context));
Icepick.restoreInstanceState(this, savedInstanceState);
Bridge.restoreInstanceState(this, savedInstanceState);

this.audioTrackAdapter = new AudioTrackAdapter(wrappedAudioTracks);
this.subtitleStreamsAdapter = new StreamItemAdapter<>(wrappedSubtitleStreams);
Expand Down Expand Up @@ -372,7 +372,7 @@ public void onDestroyView() {
@Override
public void onSaveInstanceState(@NonNull final Bundle outState) {
super.onSaveInstanceState(outState);
Icepick.saveInstanceState(this, outState);
Bridge.saveInstanceState(this, outState);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;

import com.evernote.android.state.State;

import org.schabi.newpipe.BaseFragment;
import org.schabi.newpipe.R;
import org.schabi.newpipe.error.ErrorInfo;
Expand All @@ -22,8 +24,6 @@

import java.util.concurrent.atomic.AtomicBoolean;

import icepick.State;

public abstract class BaseStateFragment<I> extends BaseFragment implements ViewContract<I> {
@State
protected AtomicBoolean wasLoading = new AtomicBoolean();
Expand Down Expand Up @@ -134,6 +134,7 @@ public void hideLoading() {
hideErrorPanel();
}

@Override
public void showEmptyState() {
isLoading.set(false);
if (emptyStateView != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;

import com.evernote.android.state.State;

import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.stream.Description;
Expand All @@ -19,8 +21,6 @@

import java.util.List;

import icepick.State;

public class DescriptionFragment extends BaseDescriptionFragment {

@State
Expand All @@ -31,7 +31,7 @@ public DescriptionFragment(final StreamInfo streamInfo) {
}

public DescriptionFragment() {
// keep empty constructor for IcePick when resuming fragment from memory
// keep empty constructor for State when resuming fragment from memory
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceManager;

import com.evernote.android.state.State;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.material.appbar.AppBarLayout;
Expand Down Expand Up @@ -128,7 +129,6 @@
import java.util.function.Consumer;

import coil.util.CoilUtils;
import icepick.State;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

import androidx.annotation.NonNull;

import com.evernote.android.state.State;

import org.schabi.newpipe.R;
import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.UserAction;
Expand All @@ -24,7 +26,6 @@
import java.util.List;
import java.util.Queue;

import icepick.State;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.disposables.Disposable;
Expand Down Expand Up @@ -143,7 +144,7 @@ public void startLoading(final boolean forceLoad) {
currentWorker = loadResult(forceLoad)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((@NonNull L result) -> {
.subscribe((@NonNull final L result) -> {
isLoading.set(false);
currentInfo = result;
currentNextPage = result.getNextPage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.evernote.android.state.State;

import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
Expand All @@ -20,8 +22,6 @@

import java.util.List;

import icepick.State;

public class ChannelAboutFragment extends BaseDescriptionFragment {
@State
protected ChannelInfo channelInfo;
Expand All @@ -31,7 +31,7 @@ public class ChannelAboutFragment extends BaseDescriptionFragment {
}

public ChannelAboutFragment() {
// keep empty constructor for IcePick when resuming fragment from memory
// keep empty constructor for State when resuming fragment from memory
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import androidx.core.view.MenuProvider;
import androidx.preference.PreferenceManager;

import com.evernote.android.state.State;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import com.jakewharton.rxbinding4.view.RxView;
Expand Down Expand Up @@ -60,7 +61,6 @@
import java.util.concurrent.TimeUnit;

import coil.util.CoilUtils;
import icepick.State;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
Expand Down Expand Up @@ -249,7 +249,7 @@ public void onDestroy() {
//////////////////////////////////////////////////////////////////////////*/

private void monitorSubscription(final ChannelInfo info) {
final Consumer<Throwable> onError = (Throwable throwable) -> {
final Consumer<Throwable> onError = (final Throwable throwable) -> {
animate(binding.channelSubscribeButton, false, 100);
showSnackBarError(new ErrorInfo(throwable, UserAction.SUBSCRIPTION_GET,
"Get subscription status", currentInfo));
Expand Down Expand Up @@ -284,14 +284,14 @@ private void monitorSubscription(final ChannelInfo info) {
}

private Function<Object, Object> mapOnSubscribe(final SubscriptionEntity subscription) {
return (@NonNull Object o) -> {
return (@NonNull final Object o) -> {
subscriptionManager.insertSubscription(subscription);
return o;
};
}

private Function<Object, Object> mapOnUnsubscribe(final SubscriptionEntity subscription) {
return (@NonNull Object o) -> {
return (@NonNull final Object o) -> {
subscriptionManager.deleteSubscription(subscription);
return o;
};
Expand All @@ -318,7 +318,7 @@ private void updateSubscription(final ChannelInfo info) {
}

private Disposable monitorSubscribeButton(final Function<Object, Object> action) {
final Consumer<Object> onNext = (@NonNull Object o) -> {
final Consumer<Object> onNext = (@NonNull final Object o) -> {
if (DEBUG) {
Log.d(TAG, "Changed subscription status to this channel!");
}
Expand All @@ -338,7 +338,7 @@ private Disposable monitorSubscribeButton(final Function<Object, Object> action)
}

private Consumer<List<SubscriptionEntity>> getSubscribeUpdateMonitor(final ChannelInfo info) {
return (List<SubscriptionEntity> subscriptionEntities) -> {
return (final List<SubscriptionEntity> subscriptionEntities) -> {
if (DEBUG) {
Log.d(TAG, "subscriptionManager.subscriptionTable.doOnNext() called with: "
+ "subscriptionEntities = [" + subscriptionEntities + "]");
Expand Down
Loading

0 comments on commit 8ada566

Please sign in to comment.