Hỏi cách truyền dữ liệu cho Widget trên android?

Mình đang làm một app dự báo thời tiết và đag xây dựng 1 cái widget cho nó mà mò bữa giờ chưa biết làm như nào để show dữ liệu lên cho nó.

Ở MainActivity thì mình dùng Room để lưu dữ liệu mình get từ api về.

private fun saveNewCityCollection(informationWeather: InformationWeather, state: Boolean = Constants.OTHER_LOCATION) {
    val weatherRepository = WeatherRepository(applicationContext)
    val cityCollection = CityCollection()
    cityCollection.cityName = informationWeather.location.name
    cityCollection.countryName = informationWeather.location.country
    cityCollection.temp = informationWeather.current.temp
    cityCollection.appTemp = informationWeather.current.appTemp
    cityCollection.humidity = informationWeather.current.humidity
    cityCollection.wind = informationWeather.current.windSpeed
    cityCollection.cloud = informationWeather.current.cloud
    cityCollection.description = informationWeather.current.condition.description
    cityCollection.icon = informationWeather.current.condition.icon
    cityCollection.date = informationWeather.current.date
    cityCollection.day = informationWeather.current.isDay
    if (location == cityCollection.cityName) {
        cityCollection.state = true
    }
    if (state) {
        cityCollection.state = true
        val editor = getSharedPreferences(getString(R.string.shared_preference_name), Context.MODE_PRIVATE).edit()
        editor.putString(Constants.NAME_LOCATION, cityCollection.cityName)
        editor.apply()
    }
    weatherRepository.insert(cityCollection, this)
}

Dây là model CityColection, mình dùng Parcelable có thể dăng dữ liệu lên dễ dàng.

class CityCollection() : Parcelable {
@PrimaryKey
@NonNull
@ColumnInfo(name = "cityname")
lateinit var cityName: String
lateinit var countryName: String
var state = Constants.OTHER_LOCATION
var temp: Float = 0F
var appTemp: Float = 0F
var humidity: Int = 0
var wind: Float = 0F
var cloud: Int = 0
var day: Int = 0
lateinit var description: String
var icon: String = "na"
var date: String = "dd/mm/yy"

constructor(parcel: Parcel) : this() {
    cityName = parcel.readString()
    countryName = parcel.readString()
    state = parcel.readByte() != 0.toByte()
    temp = parcel.readFloat()
    appTemp = parcel.readFloat()
    humidity = parcel.readInt()
    wind = parcel.readFloat()
    cloud = parcel.readInt()
    day = parcel.readInt()
    description = parcel.readString()
    icon = parcel.readString()
    date = parcel.readString()
}

override fun writeToParcel(parcel: Parcel, flags: Int) {
    parcel.writeString(cityName)
    parcel.writeString(countryName)
    parcel.writeByte(if (state) 1 else 0)
    parcel.writeFloat(temp)
    parcel.writeFloat(appTemp)
    parcel.writeInt(humidity)
    parcel.writeFloat(wind)
    parcel.writeInt(cloud)
    parcel.writeInt(day)
    parcel.writeString(description)
    parcel.writeString(icon)
    parcel.writeString(date)
}

override fun describeContents(): Int {
    return 0
}

companion object CREATOR : Parcelable.Creator<CityCollection> {
    override fun createFromParcel(parcel: Parcel): CityCollection {
        return CityCollection(parcel)
    }

    override fun newArray(size: Int): Array<CityCollection?> {
        return arrayOfNulls(size)
    }
}

}

Trong fragment của từng dự báo thành phố thì mình làm như này để nó get dữ liệu lên app của mình.

private fun initData() {
    val bundle = arguments
    if (bundle != null) {
        val cityCollection: CityCollection = bundle.getParcelable(Constants.CITY_COLLECTION) 
tvWind.text = cityCollection.wind.toInt().toString() + " km/h"
}
}

And my ViewPagerAdapter:

class ViewPagerAdapter(fm: FragmentManager, private var listCityCollection: MutableList<CityCollection>)
: FragmentStatePagerAdapter(fm) {

override fun getItem(position: Int): Fragment? {
    return newFragment(listCityCollection[position])
}

override fun getItemPosition(`object`: Any): Int {
    return PagerAdapter.POSITION_NONE
}

override fun getCount(): Int {
    return listCityCollection.size
}

private fun newFragment(cityCollection: CityCollection): FragmentShowWeatherForecast {
    val fragmentShowWeatherForecast = FragmentShowWeatherForecast()
    val bundle = Bundle()
    bundle.putParcelable(Constants.CITY_COLLECTION, cityCollection)
    fragmentShowWeatherForecast.arguments = bundle
    return fragmentShowWeatherForecast
}

}

Giờ mình cần làm như nào để get dữ liệu lên Widget. Đây là class widget của mình.

class WeatherWidget : AppWidgetProvider() {
    override fun onEnabled(context: Context?) {
        super.onEnabled(context)
        val intent = Intent(context, WeatherWidget::class.java)
        intent.action = Constants.UPDATE_WIDGET
        val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
        val alarmManager = context?.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), (Constants.UPDATE_INTERVAL * 1000).toLong(), pendingIntent)
    }

    @SuppressLint("SimpleDateFormat")
    override fun onUpdate(context: Context?, appWidgetManager: AppWidgetManager?, appWidgetIds: IntArray?) {
        if (appWidgetIds != null) {
            for (i in appWidgetIds.indices) {
                val views = RemoteViews(context?.packageName, R.layout.widget_weather)
                val openApp = Intent(context, MainActivity::class.java)
                val pIntent = PendingIntent.getActivity(context, 0, openApp, 0)
                val simpleDateFormat = SimpleDateFormat("E MM/dd")
                views.setOnClickPendingIntent(R.id.rlWidget, pIntent)
     appWidgetManager?.updateAppWidget(appWidgetIds[i], views)
            }
        }
    }
    override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {
        super.onDeleted(context, appWidgetIds)
        Toast.makeText(context, "onDeleted()", Toast.LENGTH_LONG).show()
    }

    override fun onDisabled(context: Context?) {
        super.onDisabled(context)
        val intent = Intent(context, WeatherWidget::class.java)
        intent.action = Constants.UPDATE_WIDGET
        val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
        val alarmManager = context?.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmManager.cancel(pendingIntent)
    }
}
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?