AppWidget 中的 ListView 不显示来自 firebase 的数据

问题描述

我有一个带有 ListView 的 AppWidget。当使用一个虚拟的arrayList exampleData 时,ListView 会显示它的数据。但是当我尝试从 firebase RD 检索数据到 todayList 时,我的 ListView 不显示数据。当我检查 todayList 的大小时,它不是 0,这意味着 todayList 成功检索到数据。你能帮我吗?

ListView 使用 todayList

enter image description here

ListView 使用虚拟 exampleData

enter image description here

这是我的 ExampleWidgetItemFactory 课:

internal class ExampleWidgetItemFactory(private val context: Context,intent: Intent) :
    RemoteViewsFactory {
    private lateinit var database: DatabaseReference
    private lateinit var preferences: Preferences
    private val mGoogleSignInClient: GoogleSignInClient? = null
    private lateinit var auth: FirebaseAuth
    private lateinit var user: FirebaseUser

    private lateinit var userId: String
    private lateinit var userName:String

    private var todayList: ArrayList<Task> = arraylistof()
    private val appWidgetId: Int
    private val exampleData = arraylistof(
        "one","two","three","four","five","six","seven","eight","nine","ten"
    )

    override fun onCreate() {
        //connect to data source
        //Initialize
        database = FirebaseDatabase.getInstance().reference
        auth = Firebase.auth

        //User
        user = auth.currentUser
        userId = user.uid.toString()

        //Calendar
        val calendar = Calendar.getInstance()
        val year = calendar.get(Calendar.YEAR)
        val month = calendar.get(Calendar.MONTH) + 1
        val day = calendar.get(Calendar.DAY_OF_MONTH)
        val date = String.format("%02d/%02d/%04d",day,month,year)

        database
                .child("users")
                .child(userId)
                .child("tasks")
                .addValueEventListener(object : ValueEventListener {
                    override fun onDataChange(snapshot: DataSnapshot) {
                        //Hapus data dalam arraylist agar tidak jadi penumpukan data
                        todayList.clear()

                        //Ambil semua child dalam goal dan masukan ke items
                        var items = snapshot.children
                        //Lakukan iterasi pada setiap item lalu buat class dan tambahkan ke list
                        items.forEach {
                            var task = it.getValue(Task::class.java)
                            todayList.add(task!!)
                        }
                        Log.v("gal",todayList.size.toString())
                        Log.v("gal",todayList[0].title.toString())
                        SystemClock.sleep(3000)
                    }

                    override fun onCancelled(error: DatabaseError) {
                        Todo("Not yet implemented")
                    }

                })
    }

    override fun onDataSetChanged() {

    }
    override fun onDestroy() {
        //close data source
    }

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

    override fun getViewAt(position: Int): RemoteViews {
        val views = RemoteViews(context.packageName,R.layout.example_widget_item)
        views.setTextViewText(R.id.example_widget_item_text,todayList[position].title)
        val fillIntent = Intent()
        fillIntent.putExtra(ExampleWidgetProvider().EXTRA_ITEM_POSITION,position)
        views.setonClickFillInIntent(R.id.example_widget_item_text,fillIntent)
        SystemClock.sleep(500)
        return views
    }

    override fun getLoadingView(): RemoteViews? {
        return null
    }

    override fun getViewTypeCount(): Int {
        return 1
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun hasstableIds(): Boolean {
        return true
    }

    init {
        appWidgetId = intent.getIntExtra(
            AppWidgetManager.EXTRA_APPWIDGET_ID,AppWidgetManager.INVALID_APPWIDGET_ID
        )
    }
}

**ExampleWidgetProvider **

class ExampleWidgetProvider : appwidgetprovider() {
    val ACTION_TOAST = "actionToast"
    val EXTRA_ITEM_POSITION = "extraItemPosition"

    override fun onUpdate(
        context: Context,appWidgetManager: AppWidgetManager,appWidgetIds: IntArray
    ) {
        super.onUpdate(context,appWidgetManager,appWidgetIds)
        for (appWidgetId in appWidgetIds) {
            val buttonIntent = Intent(context,HomeActivity::class.java)
            val buttonPendingIntent = PendingIntent.getActivity(
                context,buttonIntent,0
            )
            val prefs = context.getSharedPreferences(
                ExampleAppWidgetConfig().SHARED_PREFS,Context.MODE_PRIVATE
            )
            val buttonText = prefs.getString(
                ExampleAppWidgetConfig().KEY_BUTTON_TEXT + appWidgetId,"Press me"
            )
            val serviceIntent = Intent(context,ExampleWidgetService::class.java)
            serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId)
            serviceIntent.data = Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME))

            val clickIntent =
                Intent(
                    context,ExampleWidgetProvider::class.java
                )
            clickIntent.action = ACTION_TOAST

            val clickPendingIntent = PendingIntent.getbroadcast(
                context,clickIntent,0
            )

            val views = RemoteViews(context.packageName,R.layout.example_widget)
            views.setRemoteAdapter(R.id.example_widget_stack_view,serviceIntent)
            views.setEmptyView(R.id.example_widget_stack_view,R.id.example_widget_empty_view)
            views.setPendingIntentTemplate(R.id.example_widget_stack_view,clickPendingIntent)
            
            val appWidgetoptions = appWidgetManager.getAppWidgetoptions(appWidgetId)
            resizeWidget(appWidgetoptions,views)
            appWidgetManager.updateAppWidget(appWidgetId,views)
        }
    }

    override fun onAppWidgetoptionsChanged(
        context: Context,appWidgetId: Int,newOptions: Bundle
    ) {
        val views = RemoteViews(context.packageName,R.layout.example_widget)
        resizeWidget(newOptions,views)
        appWidgetManager.updateAppWidget(appWidgetId,views)
    }

    private fun resizeWidget(appWidgetoptions: Bundle,views: RemoteViews) {
        val minWidth = appWidgetoptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
        val maxWidth = appWidgetoptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
        val minHeight = appWidgetoptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
        val maxHeight = appWidgetoptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
    }

    override fun onDeleted(context: Context?,appWidgetIds: IntArray?) {
        Toast.makeText(context,"onDeleted",Toast.LENGTH_SHORT).show()
    }

    override fun onEnabled(context: Context?) {
        Toast.makeText(context,"onEnabled",Toast.LENGTH_SHORT).show()
    }

    override fun ondisabled(context: Context?) {
        Toast.makeText(context,"ondisabled",Toast.LENGTH_SHORT).show()
    }

    override fun onReceive(context: Context?,intent: Intent) {
        if (ACTION_TOAST == intent.action) {
            val clickedPosition = intent.getIntExtra(EXTRA_ITEM_POSITION,0)
            Toast.makeText(context,"Clicked position: $clickedPosition",Toast.LENGTH_SHORT).show()
        }
        super.onReceive(context,intent)
    }

}

**When I try getting size and element in `todayList`:**

    Log.v("gal",todayList.size.toString())
    Log.v("gal",todayList[0].title.toString())

**The logcat result:**

    2021-04-15 11:57:41.554 8756-8756/com.giftech.taskmastertest V/gal: 4
    2021-04-15 11:57:41.554 8756-8756/com.giftech.taskmastertest V/gal: vv

解决方法

为什么您认为您的项目应该显示在列表中?您正在从数据库中获取项目,在 todayList 中完成 forEach 和...仅此而已。你永远不会在任何地方返回这个 ArrayList,尤其是它没有设置到某个附加​​到 ListView 的适配器。看起来您已经剥离了很多代码,发布了整个课程 - 我敢打赌您的问题与异步数据库读取有关,onDataChange 的调用晚于绘图适配器/ListView,在此方法结束时,您应该可能调用 notifyDataSetChanged()

编辑:在发布整个类之后现在一切都清楚了:RemoteViewsFactory 正在根据传递给此类的数据生成视图,与适配器类似的工作。这不是从网络获取数据的时刻,因为这是异步操作,创建 RemoteViewsFactory 是一种同步方式,用于获取现有项目的视图。您应该在 extends AppWidgetProvider 类中(在 onUpdate() 方法中)获取数据,可能需要启动一些 Service 以进行异步数据获取并在存储整个数组刷新小部件 GUI 之后

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...