使用 API 数据更新小部件的 TextView

Posted

技术标签:

【中文标题】使用 API 数据更新小部件的 TextView【英文标题】:Update widget's TextView with API data 【发布时间】:2021-12-19 05:47:50 【问题描述】:

简介

我的目标是将 TextView 的文本设置为我使用 Volley 和 JSON 从 API 获得的字符串。

函数 getData() 似乎工作正常(检查 Logcat)。

问题

在 API 返回其值的那一刻,updateAppWidget(...) 已经通过,TextView 文本已经设置为“”(这是默认的静态值)。如果我在线程中添加 TextView,由于线程性质,它将无法工作。

战略

我需要一种方法来使 updateAppWidget(...) 函数等待几秒钟,直到从 API 中撤回该值。还是有更好的选择?

我编辑的唯一文件是我在此处附加的文件和 androidManifest(只是为了允许上网)。

提前致谢。

package com.bosswell.samplewidgetapi;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import android.widget.RemoteViews;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONException;
import org.json.JSONObject;


public class NewAppWidget extends AppWidgetProvider 
    static String value ="";

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId) 

        // Construct the RemoteViews object
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);

        getData(views, context);

        views.setTextViewText(R.id.appwidget_text, value);
        // Instruct the widget manager to update the widget
        appWidgetManager.updateAppWidget(appWidgetId, views);
    

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 
        Log.d("INFO", "onUpdate");

        // There may be multiple widgets active, so update all of them
        for (int appWidgetId : appWidgetIds) 
            updateAppWidget(context, appWidgetManager, appWidgetId);
        
    

    @Override
    public void onEnabled(Context context) 
        Log.d("INFO", "onEnabled");
        // Enter relevant functionality for when the first widget is created
    

    @Override
    public void onDisabled(Context context) 
        // Enter relevant functionality for when the last widget is disabled
    

    private static void getData(RemoteViews views, Context c)
        // Instantiate the RequestQueue.
        RequestQueue queue = Volley.newRequestQueue(c);
        String url ="https://www.worldtimeapi.org/api/timezone/Europe/Moscow";
        Log.d("INFO", url);
        StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                new Response.Listener<String>() 
                    @Override
                    public void onResponse(String response) 
                        try 
                            JSONObject j = new JSONObject(response);

                            value = j.getString("datetime").toString();
                            Log.d("INFO", value);
                         catch (JSONException e) 
                            value = e.getMessage();
                        
                    
                , new Response.ErrorListener() 
            @Override
            public void onErrorResponse(VolleyError error) 
                value = error.getMessage();
            
        );

        // Add the request to the RequestQueue.
        queue.add(stringRequest);
    


【问题讨论】:

如果您重复执行此类 API 相关活动,您可以查看 MVVM 和观察者,这是推荐的操作方式 使用AsyncTask调用API,然后尝试更新widget @Style-7 如何对代码进行排序以首先调用 API,然后(完成后)尝试更新小部件?如果可能,请提供正式回复,我会尽力解决。非常感谢 【参考方案1】:

您只需要在您的TextView 中设置值

响应

这样的方法

               @Override
                public void onResponse(String response) 
                    try 
                        JSONObject j = new JSONObject(response);

                        value = j.getString("datetime").toString();
                        yourTextView.setText(value.toString());
                        Log.d("INFO", value);
                     catch (JSONException e) 
                        value = e.getMessage();
                    
                

【讨论】:

感谢您的回复。更改意味着将视图作为参数传递,我这样做了,但没有奏效。 主屏幕小部件没有 setText。【参考方案2】:

    扩展 AsyncTask 以调用 API。在方法doInBackground 尝试连接到互联网,然后通过AppWidgetManager 更新小部件。

    添加到 onUpdate 方法

     @Override
     public void onUpdate( Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds )
         super.onUpdate( context, appWidgetManager, appWidgetIds );
    
         new AsyncTaskUpdater(context).execute(...);
     
    

因此,方法 onUpdate 不会更新小部件。

【讨论】:

以上是关于使用 API 数据更新小部件的 TextView的主要内容,如果未能解决你的问题,请参考以下文章

使用计时器时小部件 TextView 未更新

定期更新小部件 TextView 的简单方法

编辑小部件的文本,不受 RemotView 的限制

当运行音乐播放器的服务实际开始播放时更新小部件的 Textview

Android在小部件内获取textView值

Android主屏幕小部件未更新