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

如何解决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 之后

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?