google / agera

Reactive Programming for Android
Apache License 2.0
7.2k stars 639 forks source link

[Query]: About switch work-thread #166

Closed likai79511 closed 7 years ago

likai79511 commented 7 years ago

Hi guys, I'm coming again.,I'm a young developer,please forgive me for always disturbing you. In Agera,I know switch work-thread used Executor to submit a task to execute to on the target thread(actually is Executor). but I have a confused that how to switch to main-Thread. Of course,if I can provider a main-thread's Executor and then the rest of flows will runing on main-thread. but I don't know how to get/create main-thread's Executor. Could you give some suggestions?

Thanks Agera's fens

likai79511 commented 7 years ago

Otherwise,I have a additation question: I create a repository and while add some action on it, before the .compile() Agera will automatic add/implementation notifyIf and check old value and new value to check if need update.,right? now,I want to execute their all directives only if observe()'s observable send a dispatch(). but now,I add a updatable while their directives will be execute,it's not my expect. I try to add golazy() and trigger get() to execute, and met other problem,if add golazy() and after can not add goto().. so still can't resolve problem. I expect: only .observe(mOb) 's mOb to send dispatch() their all directives can be execute. no expect: only add updatable their all directives can be execute. please give me some help,thanks

likai79511 commented 7 years ago

Connect above, Because I need add some action on repository,so only use .repositoryWithInitialValue() not ..mutableRepository(). actually is CompiledRepository, and CompiledRepository extends BaseObservable and implementation ptotect method:observableActivated(), so just add Updatebale will be start.

maxtroy commented 7 years ago

I can't fully understand your follow-up questions. Feel free to use Chinese and I'll translate your questions to English and then answer them in both languages.

About main-thread executor: you don't need to use a main-thread executor in the flow, unless for some reason you have to go back to the main thread to retrieve more data for your computation. When you've finished producing the value in the background thread, all observers will react on the main thread (if they were registered on the main thread).

likai79511 commented 7 years ago

Sorry,my english is poor,I will be careful. About main-thread executor: I know the updatable will be runing on registered thread when receive notify. For example: I create a repository and include some actions on it, such as getFrom、transfer、mergin.. ,I want to runing getFrom on non-mainThread,for this point,I can use goto(Executor) to do it, but if I do it,the rest of flows both runing on this thread.,now I want to running transfer on main-thread, how to do it, how to switch main-thread. and note: I have no use goLazy() so only all actions finished the updatable can be runing.

likai79511 commented 7 years ago

About another problem: I create a repository use mRep = Repositories.repositoryWithInitialValue(null), and then observe a Observable use .observe(mOb). and add some actions after it,such as getGrom,thransfter etc. I expect: mRep's all actions start execute only when mOb to do dispatch() rather than mRep.addUpdatable(this). But I find mRep's actions will be start as long as execute mRep.addUpdatable(this), actually Repositories.repositoryWithInitialValue() will be create a 'CompiledRepository' and this class also implementation 'observableActivated()',so I don't know how to handle this problem. and goLazy() can't match my requirement,so can't use this.

sfcecy7i commented 7 years ago

private object MainThreadExecutor : Executor { private val handler = Handler(Looper.getMainLooper()) override fun execute(command: Runnable?) { handler.post(command) } }

ghost commented 7 years ago

Thanks @sfcecy7i !

On your second issue, the life cycle is described here. Basically, by design, and shouldn't be avoided. I think you need to reassess your design if this is what you need. Also, you can't create a repository with null, you'll have to have a concrete default value

likai79511 commented 7 years ago

@sfcecy7i @ernstsson Thanks!

maxtroy commented 7 years ago

@likai79511, you can still hack the system into your will, using creativity :)

AtomicBoolean activatedOnce = new AtomicBoolean(false);
Repository<V> repository = repositoryWithInitialValue(initialValue)
    .observe(obs)
    .onUpdatesPer...
    .check(_ -> activatedOnce.getAndSet(true)).orSkip() // creativity
    .getFrom.....
    ......
    .compile();

// in use site; suppose the repository will only have one updatable at most:
activatedOnce.set(false);
repository.addUpdatable(updatable);

repository.removeUpdatable(updatable);
likai79511 commented 7 years ago

@maxtroy Thanks. use check() to skip the rest of flows is very simply way and solve my problem. I even thought to that override repositoryWithInitialValue and extends CompiledRepository.