【发布时间】:2017-09-27 01:30:17
【问题描述】:
我有一个 RecyclerView 活动和一个 ViewModel 类。 Activity 调用 ViewModel 中的一个方法,该方法使用一个 Web 服务,并且它还观察一个 LiveData 字段。每次该方法从 Web 服务返回一个项目时,它都会将其设置为 LiveData,因此 Activity 中的观察者会收到通知,因此所有项目都会进入 RecyclerView。正如我在日志和 UI 中看到的那样,可以保证此流程正常工作。
当我在使用 Web 服务的方法中使用 Thread.slepp(500) 延迟时出现问题。
不是在 RecyclerView 中放入一个项目,然后等待 500 毫秒再放入另一个,而是等待 500 毫秒 * numberOfItems,然后将它们全部绘制在一起。
我可以保证 ViewModel 和 LiveData 设置没有问题,因为日志按预期工作,它打印所创建项目的标题,等待 500 毫秒,然后打印下一个。所以问题只在于适配器,以及方法调用完成后如何通知它。
我的问题是如何在每次调用观察者时通知适配器?
这是我对三个类的实现:
食谱列表
class RecipeList : LifecycleActivity() {
var recipeList: MutableList<Recipe> = mutableListOf()
var adapter: RecipeAdapter? = null
var viewModel: RecipeViewModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_recipe_list)
val ingredients = intent.getStringExtra("ingredients")
val term = intent.getStringExtra("term")
viewModel = ViewModelProviders.of(this).get(RecipeViewModel::class.java)
val url = "http://www.recipepuppy.com/api/?i=${ingredients}onions,garlic&q=${term}"
val layoutManager = LinearLayoutManager(this)
adapter = RecipeAdapter(this, recipeList)
rec_recycler_id.layoutManager = layoutManager
rec_recycler_id.adapter = adapter
subscribe()
viewModel?.getRecipe(url)
}
fun subscribe() {
val observer = Observer<Recipe> { recipe ->
if (recipe != null) {
Log.d("mike", "subscribe ${recipe?.title} ")
recipeList.add(recipe)
adapter?.notifyDataSetChanged()
}
}
viewModel?.mRecipe?.observe(this, observer)
}
}
RecipeViewModel
class RecipeViewModel(application: Application): AndroidViewModel(application) {
var recipes: MutableLiveData<MutableList<Recipe>>? = MutableLiveData<MutableList<Recipe>>()
var mRecipe: MutableLiveData<Recipe> = MutableLiveData()
fun getRecipe(url:String){
val requestQueue = Volley.newRequestQueue(this.getApplication())
val recipeRequest = JsonObjectRequest(Request.Method.GET,url,
Response.Listener {
response: JSONObject ->
try {
val results = response.getJSONArray("results")
for( i in 0..results.length()-1){
var recipeObj = results.getJSONObject(i)
var title = recipeObj.getString("title")
var link = recipeObj.getString("href")
var thumbnail = recipeObj.getString("thumbnail")
var ingredients = recipeObj.getString("ingredients")
var recipe = Recipe(title,ingredients,thumbnail,link)
mRecipe.value = recipe
Log.d("mike",title)
Thread.sleep(200)
}
}catch (e: JSONException){
e.printStackTrace()
}
},
Response.ErrorListener {
error: VolleyError? ->
try{
Log.d("error",error.toString())
}catch (e: JSONException){
e.printStackTrace()
}
})
requestQueue?.add(recipeRequest)
}
和 RecipeAdapter
class RecipeAdapter(val context: Context, var recipes: MutableList<Recipe>) : RecyclerView.Adapter<RecipeAdapter.ViewHolder>() {
override fun getItemCount(): Int = recipes.size
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.recipe_rec_row, null)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
holder?.bindViews(recipes[position])
}
inner class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
fun bindViews(recipe: Recipe) {
itemView.textView7.text = recipe.title
itemView.textView9.text = recipe.ingredients
itemView.button6.setOnClickListener() {
if(!recipe.link.trim().isEmpty())
context.startActivity<ShowLinkAct>("url" to recipe.link)
else
context.toast("No link available")
}
if (!recipe.thumbnail.isEmpty()) {
Picasso.with(context)
.load(recipe.thumbnail)
.placeholder(android.R.drawable.ic_menu_report_image)
.error(android.R.drawable.ic_menu_report_image)
.into(itemView.imageView)
} else {
Picasso.with(context).load(android.R.drawable.ic_menu_report_image).into(itemView.imageView)
}
}
}
}
期待您的建议,提前谢谢您
【问题讨论】:
标签: android kotlin android-recyclerview