Android RxJava生命周期管理解决方案整理

2023-10-30

一、为什么要做生命周期管理?

Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
        //TODO
    }
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
    @Override
    public void accept(String str) throws Exception {
        
    }
});

这样就是一个简单的异步处理,但是如果只是这样使用肯定是不行,因为在 Android 开发过程中,如果在进行耗时操作的时候,操作还没有结束,这个时候退出的当前 Activity,这个时候,这段代码的处理并不会因为 Activity 的退出而结束,就会导致内存泄漏等问题,严重的时候甚至会导致 APP 闪退。

二、如何管理生命周期?
1、使用CompositeDisposable 这个类,手动实现对 RxJava 的管理
原理:每次使用 RxJava,都将其生成的 Disposable 对象添加到 CompositeDisposable 对象中,并在每个界面结束(onDestroy)的时候,调用 CompositeDisposable 对象的 clear()方法取消事件。

实现过程:1.实现一个统一管理的基准类

public class CommonComposite {
 
    private CompositeDisposable mCompositeDisposable;
 
    public void addDisposable(Disposable disposable) {
        if (mCompositeDisposable == null || mCompositeDisposable.isDisposed()) {
            mCompositeDisposable = new CompositeDisposable();
        }
        mCompositeDisposable.add(disposable);
    }
 
    public void unDisposable() {
        if (mCompositeDisposable != null) {
            mCompositeDisposable.dispose();
        }
    }
}


2.在每次使用RxJava时,在最后的订阅subscribe之前,统一添加doOnSubscribe()方法,并在里面调用上面的addDisposable(),如下:

RetrofitClient.get()
        .invoke(CommandId.CASH_OUT_APPLY_LIST, params.toString())
        .doOnSubscribe(new Consumer<Disposable>() {
            @Override
            public void accept(Disposable disposable) throws Exception {
                addDisposable(disposable);
            }
        })
        .subscribe(new CommonObserver<CashOutApplyList>() {
            @Override
            public void onSuccess(CashOutApplyList data) {
                mView.updateCashOutApplyList(data.getRows());
            }
 
            @Override
            public void onError(String msg, String code) {
                mView.updateCashOutApplyList(msg);
            }
        });


3.在页面销毁的回调方法中(如onDestroy)中调用unDisposable()进行取消事件订阅

@Override
protected void onDestroy() {
    if( mPresenter!=null){
        mPresenter.unsubscribe();
    }
    super.onDestroy();
}
@Override
public void unsubscribe() {
    unDisposable();
}


2、使用RxLifecycle
Github:https://github.com/trello/RxLifecycle

实现过程:1.添加依赖

implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.1'
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.1'
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
2.继承容器类

Activity/Fragment 需要继承 RxAppCompatActivity/RxFragment,主要支持如下几种容器类:

只需要在项目中针对base类的容器中继承实现对应的Rx类即可,这一步主要是对生命周期的回调事件进行监听。

3.绑定容器生命周期

以Activity为例,主要有如下两种方法(Fragment也有同样的两种方法,只是方法名会有所不同):

bindUntilEvent(@NonNull ActivityEvent event) 
 
bindToLifecycle()
(1)bindUntilEvent(@NonNull ActivityEvent event)

//该方法指定在哪个生命周期方法调用时取消订阅

其中ActivityEvent是一个枚举类,对应于Activity的生命周期

public enum ActivityEvent {
    CREATE,
    START,
    RESUME,
    PAUSE,
    STOP,
    DESTROY
}
使用如下:指定在生命周期onDestory()时,取消订阅

@SuppressLint("AutoDispose")
    private void test() {
      Observable.interval(1, TimeUnit.SECONDS)
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        //doOnDispose:当调用 Disposable 的 dispose() 之后回调该方法
                        Log.e(TAG, "=======" + "doOnDispose:" + "=========");
                        Log.e(TAG, "=======" + "doOnDispose,Thread:" + Thread.currentThread().getName() + "=========");
                    }
                })
                .compose(bindUntilEvent(ActivityEvent.DESTROY))//指定在生命周期onDestory()时,取消订阅
                .subscribe(new Observer<Long>() {
 
                    Disposable disposable;
 
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.e(TAG, "=======" + "onSubscribe:" + "=========");
                        disposable = d;
                    }
 
                    @Override
                    public void onNext(Long aLong) {
                        Log.e(TAG, "=======" + "onNext:" + aLong + "=========");
                        Log.e(TAG, "=======" + "onNext,Thread:" + Thread.currentThread().getName() + "=========");
                    }
 
                    @Override
                    public void onError(Throwable e) {
                        Log.e(TAG, "=======" + "onError:" + "=========");
                    }
 
                    @Override
                    public void onComplete() {
                        Log.e(TAG, "=======" + "onComplete:" + "=========");
                    }
                });
    }

运行结果如下:

(2)使用bindToLifecycle()

//在某个生命周期进行绑定,在对应的生命周期进行订阅解除。具体的对应关系如下:

使用如下:在生命周期onStart()时进行绑定(就是test2()方法放在onStart()中),在onStop()时取消

@SuppressLint("AutoDispose")
    private void test2() {
        Observable.interval(1, TimeUnit.SECONDS)
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        //doOnDispose:当调用 Disposable 的 dispose() 之后回调该方法
                        Log.e(TAG, "=======" + "doOnDispose:" + "=========");
                        Log.e(TAG, "=======" + "doOnDispose,Thread:" + Thread.currentThread().getName() + "=========");
                    }
                })
                .compose(bindToLifecycle())//在某个生命周期进行绑定,在对应的生命周期进行订阅解除。如在onResume()里调用test2()进行绑定订阅,则在onPause()进行解除订阅,生命周期是两两对应的。
                .subscribe(new Observer<Long>() {
 
                    Disposable disposable;
 
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.e(TAG, "=======" + "onSubscribe:" + "=========");
                        disposable = d;
                    }
 
                    @Override
                    public void onNext(Long aLong) {
                        Log.e(TAG, "=======" + "onNext:" + aLong + "=========");
                        Log.e(TAG, "=======" + "onNext,Thread:" + Thread.currentThread().getName() + "========="); 
                    }
 
                    @Override
                    public void onError(Throwable e) {
                        Log.e(TAG, "=======" + "onError:" + "=========");
                    }
 
                    @Override
                    public void onComplete() {
                        Log.e(TAG, "=======" + "onComplete:" + "=========");
                    }
                });

运行结果如下:

原理分析:

主要就是:compose、BehaviorSubject、LifecycleTransformer、takeUntil、take、skip、combineLatest这几部分;详细参考 RxLifecycle的使用及原理分析

它的设计思路:

1.在Activity中,定义一个Observable(Subject),在不同的生命周期发射不同的事件;

2.通过compose操作符(内部实际上还是依赖takeUntil操作符),定义了上游数据,当其接收到Subject的特定事件时,取消订阅;

3.Subject的特定事件并非是ActivityEvent,而是简单的boolean,它已经内部通过combineLast操作符进行了对应的转化。

实际上,Subject和ActivityEvent对RxLifecycle的使用者来讲,是对应隐藏的。我们只需要调用它提供给我们的API,而内部的实现者我们无需考虑,但是也只有去阅读和理解了它的思想,我们才能更好的选择使用这个库

3、使用RxAutoDispose(分引入LifeCycle和不引入)
Github:https://github.com/uber/AutoDispose

实现过程:1.添加依赖

implementation 'com.uber.autodispose:autodispose:1.3.0'
implementation 'com.uber.autodispose:autodispose-android-archcomponents:1.3.0'
2.在代码中使用(两种使用方式)

//在Activity或Fragment中使用
.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))//方式一,自动绑定,在哪里注册,那么就在它的对立时期解除绑定
.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_DESTROY)))//方式二:指定解除绑定周期
private void test() {
    Observable.interval(0, 1, TimeUnit.SECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnDispose(new Action() {
                @Override
                public void run() throws Exception {
                    //doOnDispose:当调用 Disposable 的 dispose() 之后回调该方法
                    Log.e(TAG, "=======" + "doOnDispose:" + "=========");
                    Log.e(TAG, "=======" + "doOnDispose,Thread:" + Thread.currentThread().getName() + "=========");
                }
            })
            //AutoDispose在被订阅时,获取到Activity当前的生命周期,并找到对应需要结束订阅的生命周期事件
            .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))//方式一,自动绑定,在哪里注册,那么就在它的对立时期解除绑定
            .subscribe(new Observer<Long>() {
 
                Disposable disposable;
 
                @Override
                public void onSubscribe(Disposable d) {
                    Log.e(TAG, "=======" + "onSubscribe:" + "=========");
                    disposable = d;
                }
 
                @Override
                public void onNext(Long aLong) {
                    Log.e(TAG, "=======" + "onNext:" + aLong + "=========");
                    Log.e(TAG, "=======" + "onNext,Thread:" + Thread.currentThread().getName() + "=========");
                    textview.setText(String.valueOf(aLong));
                    if (aLong >= 10) {
                        disposable.dispose();
                        Log.e(TAG, "=======" + "dispose" + "=========");//这里会落后于doOnDispose执行
                    }
                }
 
                @Override
                public void onError(Throwable e) {
                    Log.e(TAG, "=======" + "onError:" + "=========");
                }
 
                @Override
                public void onComplete() {
                    Log.e(TAG, "=======" + "onComplete:" + "=========");
                }
            });
}

原理分析:

as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this))

(1)参数this:

就是Activity本身,当然它也可以是Fragment,这个参数对象只有一个要求,就是必须实现LifecycleOwner接口。LifecycleOwner接口是Google Android官方架构组件:Lifecycle的一个重要组件,在androidx中,ComponentActivity实现了这个接口,实现了这个接口的对象都拥有生命周期(Lifecycle)。这意味着,只要是实现了LifecycleOwner的类,都可以作为参数传给AutoDispose,用以控制Observable和组件生命周期的绑定。

(2)如何实现生命周期的绑定

参考RxLifecycle的原理:

1.在Activity中,定义一个Observable(Subject),在不同的生命周期发射不同的事件; 2.通过compose操作符(内部实际上还是依赖takeUntil操作符),定义了上游数据,当其接收到Subject的特定事件时,取消订阅; 3.Subject的特定事件并非是ActivityEvent,而是简单的boolean,它已经内部通过combineLast操作符进行了对应的转化

AutoDispose获取了Activity(LifecycleOwner)对象,并定义了一个新的Observable,在Activity的不同生命周期中,发射对应的事件。

和RxLifecycle很类似的是,AutoDispose在被订阅时,获取到Activity当前的生命周期,并找到对应需要结束订阅的生命周期事件:

private static final CorrespondingEventsFunction<Lifecycle.Event> DEFAULT_CORRESPONDING_EVENTS =
    lastEvent -> {
      switch (lastEvent) {
        case ON_CREATE:
          return Lifecycle.Event.ON_DESTROY;
        case ON_START:
          return Lifecycle.Event.ON_STOP;
        case ON_RESUME:
          return Lifecycle.Event.ON_PAUSE;
        case ON_PAUSE:
          return Lifecycle.Event.ON_STOP;
        case ON_STOP:
        case ON_DESTROY:
        default:
          throw new LifecycleEndedException("Lifecycle has ended! Last event was " + lastEvent);
      }
    };

也就是说,在我们的ObservableA订阅时,就已经知道了自己在Activity的哪个生命周期让AutoDispose内部自定义的ObservableB自动发射事件,ObservableA监听到这个事件时且未dispose,解除订阅避免内存泄漏。

毕竟内存泄漏是少数,更大的可能是ObservableA早就执行完任务dispose了,因此ObservableB实际上就是一个Maybe,类似于

ObservableA.takeUntil( Maybe< true > )

核心代码:

public static <E> CompletableSource resolveScopeFromLifecycle(
    Observable<E> lifecycle, final E endEvent, @Nullable final Comparator<E> comparator) {
  Predicate<E> equalityPredicate;
  if (comparator != null) {
    equalityPredicate = e -> comparator.compare(e, endEvent) >= 0;
  } else {
    equalityPredicate = e -> e.equals(endEvent);
  }
  return lifecycle.skip(1).takeUntil(equalityPredicate).ignoreElements();
}


(3)as方法执行后生成了一个什么?

as方法内部生成了一个AutoDisposeConverter对象,类似于compose,不同的是,Observable通过compose生成的对象还是Observable,但as方法生成的则是一个新的对象:

public final <R> R as(@NonNull ObservableConverter<T, ? extends R> converter)
实际上,抛开复杂的细节,AutoDispose最终将原来的Observable,生成了一个新的AutoDisposeObservable对象, 在执行订阅时,也生成了一个新的AutoDisposingObserverImpl对象

(4)AutoDispose和RxLifecycle的区别

原理相似,但是RxLifecycle有如下局限性:

1、需要继承父类(RxActivity / RxFragment等)

2、如何处处绑定生命周期?

简单的例子,我的RecyclerView的Adapter中订阅了Observable,亦或者,在MVP的架构或者 MVVM架构中,我的presenter或者我的viewModel无法直接获取RxActivity的引用(作为View 层,更应该抽象为一个接口与Presenter进行交互)。 这意味着,想要进行Observable的生命周期绑定,在RecyclerView的Adapter中,我必须要通 过将Activity作为依赖,注入到Adapter中: new ListAdapter(RxActivity activity); 而对于Presenter,我需要对View抽象接口进行instanceof 的判断:

if (view instanceof RxActivity) {

        return bindToLifecycle((RxActivity) view);

}

4、如何把AutoDispose添加到目前的Android项目中
 

(以MVP架构为例)

方式一:

(1)封装Util类

static class RxAutoDisposeUtils {
 
    private RxAutoDisposeUtils() {
    }
 
    public static <T> AutoDisposeConverter<T> bindLifecycle(LifecycleOwner lifecycleOwner) {
        return AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner));
    }
 
    public static <T> AutoDisposeConverter<T> bindLifecycle(LifecycleOwner lifecycleOwner, Lifecycle.Event event) {
        return AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner, event));
    }
 
    public static <T> AutoDisposeConverter<T> bindDestroyLifecycle(LifecycleOwner lifecycleOwner) {
        return AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner, Lifecycle.Event.ON_DESTROY));
    }
}

(2)在BaseActivity/BaseFragment中添加代码

只要持有LifecycleOwner对象,Observable都可以通过RxLifecycleUtils.bindLifecycle(LifecycleOwner)进行绑定

fun <T> bindLifecycle(): AutoDisposeConverter<T> {
        return AutoDispose.autoDisposable<T>(AndroidLifecycleScopeProvider.from(lifecycle))
 
//        return AutoDispose.autoDisposable<T>(
//            AndroidLifecycleScopeProvider.from(
//                lifecycleOwner,
//                Lifecycle.Event.ON_DESTROY
//            )
//        )
    }

(3)在任何BaseActivity的实现类中,我们都可以通过下述代码实现Observable的生命周期绑定

Observable.interval(0, 1, TimeUnit.SECONDS)
        .as(bindLifecycle())
        .subscribe()

(4)在Presenter中通过持有Activity的对象,达到Observable生命周期的绑定(类似RxLifecycle的使用)

public interface BaseView {
    <T> LifecycleTransformer<T> getActivityLifecycleProvider();
    LifecycleOwner getLifecycleOwner();
}
public class RxJavaContract {
    interface View extends BaseView {
        void onNetRequest();
    }
    interface Presenter extends BasePresenter {
        void netRequest();
    }
}

//在BaseActivity中实现如下方法

open fun <T> getActivityLifecycleProvider(): LifecycleTransformer<T> {
//        return bindToLifecycle() //可以绑定Activity生命周期
        return bindUntilEvent(ActivityEvent.DESTROY);//可以绑定Activity生命周期
    }
 
    fun getLifecycleOwner(): LifecycleOwner {
        return this
    }
public class RxJavaPresenter implements RxJavaContract.Presenter {
    private RxJavaContract.View mView;
    Observable.interval(1, TimeUnit.SECONDS)
            .compose(mView.getActivityLifecycleProvider())
            .subscribe()
}

方式二:使用Google官方Lifecycle组件

(1)首先让我们的IPresenter接口实现LifecycleObserver接口

//实现了 LifecycleObserver 接口的类可以和实现了 LifecycleOwner 接口的类无缝工作
//,因为 LifecycleOwner 可以提供一个 Lifecycle 对象,而 LifecycleObserver 就正
//需要对这个 Lifecycle 对象进行监听呢。 LifecycleOwner 是从特定的类(比如
// Activity 或者 Fragment 等)中抽象出来的Lifecycle 的持有者

interface IPresenter : LifecycleObserver {
    //使用Google官方Lifecycle组件
    // 使用注解  @OnLifecycleEvent 来表明该方法需要监听指定的生命周期事件
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate(@NotNull owner: LifecycleOwner)
 
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy(@NotNull owner: LifecycleOwner)
 
    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    fun onLifecycleChanged(@NotNull owner: LifecycleOwner, @NotNull event: Lifecycle.Event)
}

(2)然后在BasePresenter中管理LifecycleOwner

abstract class BaseNewPresenter :
    IPresenter {

    private lateinit var lifecycleOwner: LifecycleOwner
 
    override fun onCreate(owner: LifecycleOwner) {
        Log.e("LifecycleOwner", "=======" + "onCreate:" + "=========")
        this.lifecycleOwner = owner
    }
 
    override fun onDestroy(owner: LifecycleOwner) {
 
    }
 
    override fun onLifecycleChanged(owner: LifecycleOwner, event: Lifecycle.Event) {
 
    }
 
    fun <T> bindLifecycle(): AutoDisposeConverter<T> {
        return AutoDispose.autoDisposable<T>(AndroidLifecycleScopeProvider.from(lifecycleOwner))
 
//        return AutoDispose.autoDisposable<T>(
//            AndroidLifecycleScopeProvider.from(
//                lifecycleOwner,
//                Lifecycle.Event.ON_DESTROY
//            )
//        )
    }
}

(3)最后在Activity中添加Presenter为观察者,观察Activity的生命周期

abstract class BaseNewMvpActivity<P : IPresenter> : BaseNewActivity(){
    lateinit var presenter: P
 
    override fun onCreate(savedInstanceState: Bundle?) {
        presenter = createPresenter()
        //这一行,如此每当Activity发生了对应的生命周期改变,Presenter就会执行
        //对应事件注解的方法
        lifecycle.addObserver(presenter)
        super.onCreate(savedInstanceState)
    }
}

(4)Presenter中的使用

public class RxAutoDisposePresenter extends BaseNewPresenter implements RxAutoDisposeContract.Presenter {
 
    private RxAutoDisposeContract.View mView;
    private Context mContext;
    private String TAG = RxAutoDisposePresenter.class.getSimpleName();
 
    public RxAutoDisposePresenter(Context context, RxAutoDisposeContract.View view) {
        this.mContext = context;
        this.mView = view;
    }
 
    @Override
    public void netRequest() {
        Observable.interval(0, 1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        //doOnDispose:当调用 Disposable 的 dispose() 之后回调该方法
                        Log.e(TAG, "=======" + "doOnDispose:" + "=========");
                        Log.e(TAG, "=======" + "doOnDispose,Thread:" + Thread.currentThread().getName() + "=========");
                    }
                })
                .as(bindLifecycle())//方式二:指定解除绑定周期
                .subscribe(new BaseObserver<Long>() {
                    @Override
                    public void onSuccess(Long data) {
                        Log.e(TAG, "=======" + "onSuccess:" + data + "=========");
                        mView.onNetRequest(data);
                    }
 
                    @Override
                    public void onError(String msg, String code) {
                        mView.onNetRequest(Long.parseLong(code));
                    }
                });
    }
}

我们即使在Presenter中,也能任意使用myObservable.as(bindLifecycle()) 方法了,和第一种方式相比,更加灵活。

 

原文链接:https://blog.csdn.net/fitaotao/article/details/117522260

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android RxJava生命周期管理解决方案整理 的相关文章

  • Android:如何暂停和恢复可运行线程?

    我正在使用 postDelayed 可运行线程 当我按下按钮时 我需要暂停并恢复该线程 请任何人帮助我 这是我的主题 protected void animation music6 music4 postDelayed new Runnab
  • 使用同一个侦听器的多个活动

    我有 4 个活动 它们都包含一个 xml 页脚 其中包含 4 个按钮 每个活动一个 我现在想为这些按钮设置 onclicklistener 它是页脚中的自制菜单 问题是 如何使用侦听器以便重用代码 我有两个想法 创建一个实现 onclick
  • 音频流的最佳实践

    我正在编写一个应用程序来播放远程服务器的音频 我尝试了多种方法来实现流音频 但它们对我来说都不够好 这就是我尝试过的 幼稚地使用 MediaPlayer 就像是 MediaPlayer player new MediaPlayer play
  • Android Camera.takePicture() 有时不返回?

    我正在编写一个Android 拍照应用程序 该代码在 onPreviewFrame byte data Cameracamera 中从预览中获取帧后进行一些处理 问题在于 android hardware Camera 的函数 takePi
  • 虚拟回调接口

    在 Eclipse 为您创建的来自 Google 的示例主从流代码中 片段中包含以下内容 private Callbacks mCallbacks sDummyCallbacks public interface Callbacks pub
  • 无法在 Android Studio 中导出签名的 APK

    当我使用keytool list keystore path to keyfile jks并提供我的密码 我可以看到那里的条目 但是当我在尝试使用相同的密码生成签名的 APK 时使用相同的密码时 我收到错误 无法加载密钥库 密钥库被篡改 或
  • 当我单击“完成”键时,Android OnEditorActionListener() actionId 给出 0

    我创建了一个键盘 当用户输入数字时 它会输入特定的 EditText 但是当用户单击Done关键 它没有去setOnEditorActionListener但它关闭了键盘 这是我的代码 final EditText txtQty new E
  • 如何使用 RecyclerView 创建此布局?

    我正在尝试使用这种类型的布局创建回收器视图 这些项目是字符串 可以以不同的大小出现 我不知道每行中有多少项目 我可以使用 StaggeredGridLayoutManager 来做到这一点吗 该图像只是一个假示例 每行可以有更多项目 您可能
  • java.lang.IllegalAccessError:预验证类中的类引用在运行测试项目时解析为意外实现?

    在实施项目工作正常之后 我使用第三方库 zxing 实施了项目 然后在我编写了一个测试项目对我的项目进行单元测试之后 运行测试项目后 主项目 类及其方法没有给出任何信息错误 但如果在主项目的该方法中使用任何 zxing 框架类 则会在运行时
  • 在 NFC 标签扫描期间,onNewIntent() 内的intent.getAction() 为 null

    这是我第一次使用 NFC 标签 我在清单中声明了 NFC 扫描活动
  • Android L,使用 joda.time 库的异常

    该应用程序适用于所有设备 包括 nexus 5 和 nexus 7 在 Android L 预览版上运行相同的应用程序时 应用程序崩溃了 我一直在调试 并且调用 DateTime 构造函数发现了异常 public static String
  • Android 和 Google 地图内部片段以及其他控件和 viewpager

    我是android编程新手 我有一个带有 3 个页面 片段 的小应用程序 使用 pageradapter 和 viewpager 在它们之间滑动 其中一个页面包含复选框 和其他控件 和地图 我的问题是程序在启动时崩溃 Fragment co
  • 如何在 60 分钟后删除共享首选项

    我想存储登录数据 但希望在 60 分钟后删除该数据 执行此操作的正确方法是什么 在这 60 分钟内可以关闭 停止 打开应用程序 我不想使用内部数据库 这是我的访问代码SharedPreferences sharedpreferences g
  • Android 操作项上的通知徽章

    我想在操作栏中放置的购物车图像上添加一个通知徽章 并以编程方式操作它 有帮助吗 您可以显示自定义MenuItem on ActionBar通过创建一个custom layout for MenuItem 要设置自定义布局 您必须使用菜单项属
  • 文本视图不显示全文

    我正在使用 TableLayout 和 TableRow 创建一个简单的布局 其中包含两个 TextView 这是代码的一部分
  • 了解应用程序在后台时何时收到 Firebase 消息

    我知道这个标题有同样的问题 但不幸的是它没有得到正确的回答 它被接受了 here https stackoverflow com questions 37711082 how to handle notification when app
  • 使 Recyclerview 固定高度并可滚动

    已解决以下检查答案 所以我试图为我的 Android 应用程序创建评论功能 我想在 recyclerview 中显示评论 然后在 recyclerview 下方有一个按钮和文本视图来添加评论 我想让 recyclerview 具有一定的高度
  • 如何知道我的应用程序的活动计数?

    我的应用程序中有多项活动 请考虑以下案例 Activity A 调用 Activity B B 调用 C 当用户按后退键时 C 生成通知并转到 B 现在再次按后退 因此将显示 A 再次按后退键也会终止 A 并显示通知 现在 当用户按下通知图
  • 用于请求带有临时缓存的远程 Observable 的 RxJava 模式

    用例是这样的 我想暂时缓存最新发出的昂贵的Observable响应 但在它过期后 返回到昂贵的源Observable并再次缓存它 等等 一个非常基本的网络缓存场景 但我真的很难让它工作 private Observable
  • TabLayout 的不同 tabMode

    我正在使用 ViewPager 和 TabLayout 如果选项卡可以放置在显示 tabMode 上 则它们必须是 app tabMode fixed else app tabMode scrollable 我怎样才能做到这一点 我不明白你

随机推荐

  • Service Intent must be explicit的解决方法

    http blog csdn net shenzhonglaoxu article details 42708723 java view plain copy final Intent intent new Intent intent se
  • jeesite框架中获取登入用户的登入名

    jeesite框架中获取登入用户的登入名 UserUtils getUserName
  • 17 张图实战 + 理清 K8S 网络排错思路,硬核!

    作者 Cylon出处 https u kubeinfo cn R35JNc Overview 本文将引入一个思路 在 Kubernetes 集群发生网络异常时如何排查 文章将引入 Kubernetes 集群中网络排查的思路 包含网络异常模型
  • 算法笔记之旅——问题B:出租车费

    题目描述 某市出租车计价规则如下 起步4公里10元 即使你的行程没超过4公里 接下来的4公里 每公里2元 之后每公里2 4元 行程的最后一段即使不到1公里 也当作1公里计费 一个乘客可以根据行程公里数合理安排坐车方式来使自己的打车费最小 例
  • 空间误差分析:统一的应用导向处理(Matlab代码实现)

    个人主页 研学社的博客 欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 本文关
  • SVN软件中patch的的运用以及patch介绍

    什么是patch patch就是补丁 在程序中就是和原来相比有差异的部分 生活中常见的就是程序升级 假设我们用手机下载某个软件显示是100M大小 第一次安装时就需要下载100M大小的安装包 当安装完成后 后续会收到软件升级的提醒 升级包可能
  • Vuforia提高识别图星级

    本文转载自http blog csdn net unity3d xyz article details 50638007 高通的识别图上传到后台以后我们可以看有星级评定 星值最大为5星 星值越大有以下好处 1 识别图越容易识别 2 识别出来
  • 从零开始的RVOS: Referring Video Object Segmentation

    最近新接触到一个与VOS相关的任务 叫做Referring VOS 该任务基于文本描述对视频中特定目标进行分割 是一个新兴的跨模态CV任务 数据集 1 静态推断图像分割数据集 虽然RVOS是视频任务 但根据以往的经验和相关文章的方法 可以使
  • 水文模型有哪些?SWAT模型、VIC模型、HEC模型、HSPF模型、HYPE模型、SWMM模型、FVCOM模型、Delft3D模型等应用

    目录 从小白到精通SWAT模型学习建模方法 实例应用 高级进阶 R VIC模型融合实践技术应用及未来气候变化模型预测 HEC RAS一维 二维建模方法及实践技术应用 HEC HMS水文模型实践技术应用 HSPF 模型应用 HYPE分布式水文
  • Service的两种启动方式

    在Android开发的过程中 Service是一个非常重要的组件 它的生命周期里面有几个特别重要的方法 Service的生命周期 onCreate 当服务创建的时候调用 onStartCommand startServcie的时候会调用这个
  • RFID作业(第三次)

    1 通信系统中为什么要进行编码和解码 常见的编码方法有哪些 信源编码是指将模拟信号转换成数字信号 或将数字信号编码成更合适传输的数字信号 换句话来说 通信系统编码和解码是为了让信号更适合传输 常见的编码方法有1 反向不归零编码 2 曼彻斯特
  • ListView的复用问题,点击条目变色.不复用

    主要的是3个类 包含activity application 和一个adpter 内部的细节在代码中都有详细的注释 可以参考 application public class MyApplication extends Applicatio
  • PyQt5学习笔记16----PyQt信号和槽传递额外参数

    使用Pyqt编程过程中 经常会遇到给槽函数传递额外参数的情况 但是信号 槽机制只是指定信号如何连接到槽 信号定义的参数被传递给槽 而额外的参数 用户定义 不能直接传递 而传递额外参数又是很有用处 你可能使用一个槽处理多个组件的信号 有时要传
  • GIT实战篇,教你如何使用GIT可视化工具

    系列文章目录 手把手教你安装Git 萌新迈向专业的必备一步 GIT命令只会抄却不理解 看完原理才能事半功倍 快速上手GIT命令 现学也能登堂入室 GIT实战篇 教你如何使用GIT可视化工具 系列文章目录 一 GIT有哪些常用工具 1 Git
  • 图像增强 数据增强

    目录 python opncv 数据增强 亮度 opencv 亮度饱和度增强 vgg19图像增强 c opencv 图像增强 python opncv 数据增强 亮度 def data augment image brightness fa
  • 从零开始的python教程:全面又好用的学习资料

    1 耳熟能详的Python自学网站 廖雪峰python学习网站 推荐理由 全面成体系的python学习内容 概括起来其实就是免费且全面 而且里面的知识讲解也十分恰当 所举的例子也十分的形象 不足 知识之间的梯度对于刚学习python的学习者
  • 浅谈:VS中解决Bug的几个简单实用调试技巧

    在写这篇文章之前 就已经有不少读者来问我 有没有调试方面的文章 给推荐 思前想后 笔者决定自己研究一下调试的技巧 以便更好的使用VS 对于现在不少初学C语言的学者 大部分开始使用VS2019 或者VS2022 但是对于代码出现了错误 该怎么
  • Idea运行springboot项目(保姆级教学)

    大家好 我是CZ淡陌 一名专注以理论为基础实战为主的技术博主 将再这里为大家分享优质的实战项目 本人在Java毕业设计领域有多年的经验 陆续会更新更多优质的Java实战项目 希望你能有所收获 少走一些弯路 向着优秀程序员前行 Java项目精
  • 一、深入理解redis之需要掌握的知识点

    导读 从本章开始我们将要深入讲解redis 讲解的内容包括 redis的基础数据类型及应用场景 数据存储 持久化方式 RDB AOF redis集群进化过程 redis中AKF问题解决方案 redis中CAP问题解决方案 redis的分布式
  • Android RxJava生命周期管理解决方案整理

    一 为什么要做生命周期管理 Observable create new ObservableOnSubscribe