Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/192.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android RxKotlin-订阅错误,观察到主题在活动之外的线程更改?_Android_Multithreading_Kotlin Android Extensions_Rx Kotlin_Rx Kotlin2 - Fatal编程技术网

Android RxKotlin-订阅错误,观察到主题在活动之外的线程更改?

Android RxKotlin-订阅错误,观察到主题在活动之外的线程更改?,android,multithreading,kotlin-android-extensions,rx-kotlin,rx-kotlin2,Android,Multithreading,Kotlin Android Extensions,Rx Kotlin,Rx Kotlin2,我有一个在随机时刻生成不同字符串的对象,我需要向这个生成器进行sudscribe,以获取这些字符串并将其提供给ui(可能是不同活动中的多个订阅者)。 假设我得到了以下代码: 发电机: class Generator { private var stringToGenerate = "" var subject: BehaviorSubject<String> = BehaviorSubject.create<String>() init {

我有一个在随机时刻生成不同字符串的对象,我需要向这个生成器进行sudscribe,以获取这些字符串并将其提供给ui(可能是不同活动中的多个订阅者)。 假设我得到了以下代码:

发电机:

class Generator {

    private var stringToGenerate = ""

    var subject: BehaviorSubject<String> = BehaviorSubject.create<String>()

    init {
        //seems like these instructions are skipped
        subject
                .subscribeOn(AndroidSchedulers.mainThread())
                .doOnNext { t -> Log.i("subject doOnNext", Thread.currentThread().name + " " + Thread.currentThread().id) }
                .observeOn(AndroidSchedulers.mainThread())
                .map { _ -> Log.i("subject map", Thread.currentThread().name + " " + Thread.currentThread().id) }

        //imitation of async creating of strings in separate thread
        timer("timerThread", false, 2000L, 2000L) {
            stringToGenerate = System.currentTimeMillis().toString()
            subject.onNext(stringToGenerate)
        }
    }
}
类生成器{
private var stringToGenerate=“”
var subject:BehaviorSubject=BehaviorSubject.create()
初始化{
//似乎这些说明被跳过了
主题
.subscribeOn(AndroidSchedulers.mainThread())
.doOnNext{t->Log.i(“主题doOnNext”,Thread.currentThread().name+“”+Thread.currentThread().id)}
.observeOn(AndroidSchedulers.mainThread())
.map{->Log.i(“主题映射”,Thread.currentThread().name+“”+Thread.currentThread().id)}
//模拟在单独线程中异步创建字符串
计时器(“timerThread”,假,2000L,2000L){
stringToGenerate=System.currentTimeMillis().toString()
subject.onNext(stringToGenerate)
}
}
}
必须使用生成字符串的活动之一:

class TestActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_test)

        val wrongThreadObserver = object : Observer<String> {
            override fun onComplete() {
            }

            override fun onSubscribe(d: Disposable) {
            }

            override fun onNext(t: String) {
                Log.i("wrongThreadObserver", Thread.currentThread().name + " " + Thread.currentThread().id)
            }

            override fun onError(e: Throwable) {
            }
        }

        val generator = Generator()
        generator.subject.subscribe(wrongThreadObserver)

        //for correct work illustration
        val correctThreadObserver = object : Observer<String> {
            override fun onComplete() {
            }

            override fun onSubscribe(d: Disposable) {
            }

            override fun onNext(t: String) {
                Log.i("correctThreadObserver", Thread.currentThread().name + " " + Thread.currentThread().id)
            }

            override fun onError(e: Throwable) {
            }
        }

        val mainThreadSubject = BehaviorSubject.create<String>()
        mainThreadSubject
                .doOnNext { obj -> Log.i("correctThread doOnNext", Thread.currentThread().name + " " + Thread.currentThread().id) }
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
                .subscribe(correctThreadObserver)
        mainThreadSubject.onNext("test thread")
        val handler = Handler()
        handler.postDelayed({ mainThreadSubject.onNext("test thread 2") }, 1000)
        handler.postDelayed({ mainThreadSubject.onNext("test thread 3") }, 2000)
    }
}
类测试活动:AppCompatActivity(){ 重写创建时的乐趣(savedInstanceState:Bundle?){ super.onCreate(savedInstanceState) setContentView(R.layout.activity\u测试) val=对象:观察者{ 覆盖有趣的onComplete(){ } 覆盖订阅的乐趣(d:一次性){ } 覆盖文本(t:字符串){ Log.i(“错误线程观察者”,Thread.currentThread().name+“”+Thread.currentThread().id) } 覆盖有趣的错误(e:可丢弃){ } } val生成器=生成器() generator.subject.subscribe(观察者) //正确的工作说明 val correctThreadObserver=对象:观察者{ 覆盖有趣的onComplete(){ } 覆盖订阅的乐趣(d:一次性){ } 覆盖文本(t:字符串){ Log.i(“correctThreadObserver”,Thread.currentThread().name+“”+Thread.currentThread().id) } 覆盖有趣的错误(e:可丢弃){ } } val mainThreadSubject=BehaviorSubject.create() 主语 .doOnNext{obj->Log.i(“correctThread doOnNext”,Thread.currentThread().name+“”+Thread.currentThread().id)} .subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()) .订阅(观察员) mainThreadSubject.onNext(“测试线程”) val handler=handler() handler.postDelayed({mainThreadSubject.onNext(“测试线程2”)},1000) handler.postDelayed({mainThreadSubject.onNext(“测试线程3”)},2000) } } 在本例中,correctThreadObserver仅在活动中创建,工作正常,但ErrorThreadObserver在计时器线程中保持工作,似乎它忽略了生成器中的指令subscribeOn、ObserveOn、doOnNext,无论这些指令在初始化中、计时器线程中的何处调用,在活动中,通过从生成器获取对象-ErrorThreadObserver仍在计时器线程中工作。 所以日志是:

I/D下一步:主2

I/correctThreadObserver:RxNewThreadScheduler-1 941

I/D下一步:主2

I/correctThreadObserver:RxNewThreadScheduler-1 941

I/O线程观察员:时间读取937

I/D下一步:主2

I/correctThreadObserver:RxNewThreadScheduler-1 941

I/O线程观察员:时间读取937

I/O线程观察员:时间读取937

I/O线程观察员:时间读取937

没有
doOnNext
ErrorThreadObserver的主线程

我做错了什么?

我找到了以下解决方案: 我们必须订阅
observeable
,而不是
Subject
,因此我们必须使用方法
observeOn()
的结果,而不是对象“Subject”本身。 如果需要多个订阅,我们可以将
observeOn
的结果缓存在单独的变量中:

//in Generator
.......
var observableInSeparateVar = subject.observeOn(AndroidSchedulers.mainThread())
.......

//in TestActivity
.......
generator.observableInSeparateVar.subscribe(wrongThreadObserver)
.......
此外,我们还可以调用
observeOn()
,在之后进行主题和订阅:

//in TestActivity
.......
generator.subject
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(wrongThreadObserver)

observeOn
替换
subscribeOn
,我认为它应该可以工作