I’m trying to load a RecyclerView with JSON data in a local file located in ‘assets’.
Activity:
class RecipesActivity : AppCompatActivity(), RecipeAdapter.RecipeItemListener {
private lateinit var binding : ActivityRecipesBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRecipesBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.mainToolBar.toolbar)
supportActionBar?.setDisplayShowTitleEnabled(false)
val viewModel : RecipeViewModel by viewModels()
viewModel.getRecipes().observe(this) {
binding.recipesRecyclerView.adapter = RecipeAdapter(this, it, this)
}
}
Adapter:
class RecipeAdapter (val context : Context,
private val recipes : List<Recipe>,
private val itemListener : RecipeItemListener) : RecyclerView.Adapter<RecipeAdapter.RecipeViewHolder>() {
inner class RecipeViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
var recipeTextView = itemView.findViewById<TextView>(R.id.recipeTextView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipeViewHolder {
val inflator = LayoutInflater.from(parent.context)
val view = inflator.inflate(R.layout.item_recipe, parent, false)
return RecipeViewHolder(view)
}
override fun onBindViewHolder(viewHolder: RecipeViewHolder, position: Int) {
val recipe = recipes[position]
with (viewHolder) {
recipeTextView.text = recipe.dish
itemView.setOnClickListener {
itemListener.recipeSelected(recipe)
}
}
}
override fun getItemCount(): Int {
return recipes.size
}
interface RecipeItemListener {
fun recipeSelected(recipe : Recipe)
}
ViewModel:
class RecipeViewModel : ViewModel() {
private var recipes = MutableLiveData<List<Recipe>>()
init {
val gson = Gson()
val inputStream: InputStream = assets.open("recipes.json")
val jsonStr = inputStream.bufferedReader().use { it.readText() }
val recipeList = gson.fromJson(jsonStr, Array<Recipe>::class.java).toList()
recipes.value = recipeList
Log.i("json string", "${recipeList.toString()}")
}
fun getRecipes() : LiveData<List<Recipe>> {
return recipes
}
Everything works besides getting the data, just not sure how to do that. I tried passing the context in as a parameter to the constructor, but I don’t know where else I need to update because it says no empty constructor present. I added an empty constructor but it kept the recyclerview empty.
2
Answers
I used this to load a JSON-list from assets:
First you do not need to init RecipeAdapter each time the LiveData changed:
You can call:
And init it before. Second in your RecyclerView check for: