Android 如何用Rx等价物替换AsyncTask和AsyncTaskLoader? 背景
一些文章声称Rx可以取代AsyncTask和AsyncTaskLoader。 看到Rx通常会使代码变短,我试着深入研究各种示例和它的工作原理 问题 我发现的所有示例和文章,包括Github repos,似乎都不能很好地取代AsyncTask和AsyncTaskLoader:Android 如何用Rx等价物替换AsyncTask和AsyncTaskLoader? 背景,android,android-asynctask,rx-android,asynctaskloader,Android,Android Asynctask,Rx Android,Asynctaskloader,一些文章声称Rx可以取代AsyncTask和AsyncTaskLoader。 看到Rx通常会使代码变短,我试着深入研究各种示例和它的工作原理 问题 我发现的所有示例和文章,包括Github repos,似乎都不能很好地取代AsyncTask和AsyncTaskLoader: 找不到如何取消一个或多个任务(包括中断线程)。这对于AsyncTask尤其重要,AsyncTask通常用于RecyclerView和ListView。这也可以在AsyncTaskLoader上完成,但需要比调用“cancel
- -这实际上为处理AsyncTaskLoader提供了一种很酷的方法,因为它可以缓存结果。但是,这些示例根本不起作用(包括构建它们),因为它们非常旧
- ,-所有这些都主要讨论RxJava,而不是AsyncTask或AsyncTaskLoader的替换
- -需要取消订阅,即使它没有说需要
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportLoaderManager.initLoader(1, Bundle.EMPTY, object : LoaderCallbacks<Int> {
override fun onCreateLoader(id: Int, args: Bundle): Loader<Int> {
Log.d("AppLog", "onCreateLoader")
return MyLoader(this@MainActivity)
}
override fun onLoadFinished(loader: Loader<Int>, data: Int?) {
Log.d("AppLog", "done:" + data!!)
}
override fun onLoaderReset(loader: Loader<Int>) {}
})
}
private class MyLoader(context: Context) : AsyncTaskLoader<Int>(context) {
override fun onStartLoading() {
super.onStartLoading()
forceLoad()
}
override fun loadInBackground(): Int {
Log.d("AppLog", "loadInBackground")
try {
Thread.sleep(10000)
} catch (e: InterruptedException) {
e.printStackTrace()
}
return 123
}
}
}
class MainActivity:AppCompatActivity(){
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initLoader(1,Bundle.EMPTY,对象:LoaderCallbacks{
重写onCreateLoader(id:Int,args:Bundle):Loader{
Log.d(“AppLog”、“onCreateLoader”)
回程装载机(this@MainActivity)
}
覆盖乐趣onLoadFinished(加载程序:加载程序,数据:Int?){
Log.d(“AppLog”,“done:+data!!)
}
重写有趣的onLoaderReset(加载程序:加载程序){}
})
}
私有类MyLoader(上下文:上下文):AsyncTaskLoader(上下文){
覆盖启动加载()的乐趣{
super.onStartLoading()
力载荷()
}
覆盖乐趣加载背景():Int{
日志d(“应用日志”、“加载背景”)
试一试{
线程。睡眠(10000)
}捕获(e:中断异常){
e、 printStackTrace()
}
返回123
}
}
}
对于AsyncTask,通常我们将它设置为每个ViewHolder的一个字段,并在onBindViewHolder上以及当activity/fragment被销毁时取消它(检查所有仍然挂起或运行的)
类似这样的内容(样本尽可能短,当然应该根据需要进行更改):
class AsyncTaskActivity:AppCompatActivity(){
内部val mTasks=HashSet()
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity\u async\u任务)
val recyclerView=findviewbyd(R.id.recyclerView)
recyclerView.layoutManager=LinearLayoutManager(此,LinearLayoutManager.VERTICAL,false)
recyclerView.adapter=对象:adapter(){
重写CreateViewHolder(父级:ViewGroup,viewType:Int):MyViewHolder{
返回MyViewHolder(LayoutFlater.from(this@AsyncTaskActivity).充气(android.R.layout.simple_list_item_1,父项,false))
}
@SuppressLint(“StaticFieldLeak”)
覆盖onBindViewHolder(holder:MyViewHolder,位置:Int){
holder.tv.text=“正在加载…”
if(holder.task!=null){
holder.task!!.cancel(真)
mTasks.remove(holder.task!!)
}
holder.task=对象:AsyncTask(){
覆盖有趣的背景(vararg voids:Void):Void{
对于(0..100中的i)
试一试{
线程。睡眠(5)
出版进度(一)
}捕获(e:中断异常){
e、 printStackTrace()
}
返回空
}
重写进程更新(vararg值:Int?){
super.onProgressUpdate(*值)
holder.tv.text=“进度:”+值[0]
}
重写onPostExecute(避免:无效?){
super.onPostExecute(避免)
mTasks.remove(holder.task)
holder.tv.text=“完成:”+位置
holder.task=null
}
}.execute()
}
重写getItemCount():Int{
返回1000
}
}
}
重写onDestroy(){
super.ondestory()
用于(mTasks中的任务)
任务。取消(true)
}
私有类MyViewHolder(itemView:View):ViewHolder(itemView){
内部var电视:文本视图
内部变量任务:AsyncTask?=null
初始化{
tv=itemView.findViewById(android.R.id.text1)
}
}
}
让我提前告诉你,我在RxJava方面的经验并不像有些人所说的那样先进。我只知道用RxJava+RxAndroid替换AsyncTask
。例如,让我们转换您的AsyncTask
class AsyncTaskActivity : AppCompatActivity() {
internal val mTasks = HashSet<AsyncTask<Void, Int, Void>>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_async_task)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
recyclerView.adapter = object : Adapter<MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(LayoutInflater.from(this@AsyncTaskActivity).inflate(android.R.layout.simple_list_item_1, parent, false))
}
@SuppressLint("StaticFieldLeak")
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.tv.text = "loading..."
if (holder.task != null) {
holder.task!!.cancel(true)
mTasks.remove(holder.task!!)
}
holder.task = object : AsyncTask<Void, Int, Void>() {
override fun doInBackground(vararg voids: Void): Void? {
for (i in 0..100)
try {
Thread.sleep(5)
publishProgress(i)
} catch (e: InterruptedException) {
e.printStackTrace()
}
return null
}
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
holder.tv.text = "progress:" + values[0]
}
override fun onPostExecute(aVoid: Void?) {
super.onPostExecute(aVoid)
mTasks.remove(holder.task)
holder.tv.text = "done:" + position
holder.task = null
}
}.execute()
}
override fun getItemCount(): Int {
return 1000
}
}
}
override fun onDestroy() {
super.onDestroy()
for (task in mTasks)
task.cancel(true)
}
private class MyViewHolder(itemView: View) : ViewHolder(itemView) {
internal var tv: TextView
internal var task: AsyncTask<Void, Int, Void>? = null
init {
tv = itemView.findViewById(android.R.id.text1)
}
}
}
Observable
.create <Int> { emitter ->
try {
for (i in 0..100) {
Thread.sleep(5)
emitter.onNext(i)
}
} catch (e: InterruptedException) {
emitter.onError(e)
}
emitter.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ i ->
holder.tv.text = "progress:" + i
}, { e ->
e.printStackTrace()
}, {
holder.tv.text = "done:" + position
})