Android 小部件上的主题

Threads on Android widget

我正在尝试制作一个小部件时钟。

在我的 MainActivity 上,使用 runOnUiThread 可以完美显示时钟。 由于小部件不扩展 "activity" 我无法运行 OnUiThread。
但是,当我尝试将 Thread 与小部件一起使用时,出现错误(或)一个空白小部件。

public class NewAppWidget extends AppWidgetProvider {
static Context cont;
static AppWidgetManager awm;
static int awid;
static Thread  t;
static RemoteViews views;
static String timeText;
static String dateText;
public static Bitmap BuildUpdate(String txttime, int size,Context context){
    Paint paint= new Paint();
    paint.setTextSize(size);
    Typeface 
    custTface=Typeface.createFromAsset(context.getAssets(),"fonts/Lato-Regular.ttf");
    paint.setTypeface(custTface);
    paint.setColor(Color.WHITE);
    paint.setTextAlign(Paint.Align.LEFT);
    paint.setSubpixelText(true);
    paint.setAntiAlias(true);
    // - in the  next line is highly important.
    float baseline  = -paint.ascent();
    int width =(int) paint.measureText(txttime+0.5f);
    int height= (int) (baseline+paint.descent()+0.5f);
    Bitmap image = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
    Canvas canvas=new Canvas(image);
    canvas.drawText(txttime,0,baseline,paint);
    return image;
}

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                            int appWidgetId) {
     views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
     cont=context;
     awm=appWidgetManager;
     awid=appWidgetId;
      t = new Thread() {
         @Override
         public void run() {
             while (!isInterrupted()){
                 try {
                     t.sleep(1000);
                     new Thread(new Runnable(){
                         @Override
                         public void run() {
                             long date = System.currentTimeMillis();
                             SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
                             SimpleDateFormat sdf2 = new SimpleDateFormat("hh-mm-ss a");
                             timeText = sdf2.format(date);
                             dateText = sdf.format(date);
                             views.setImageViewBitmap(R.id.txtTime, BuildUpdate(timeText, 100, cont));
                             views.setImageViewBitmap(R.id.txtDate, BuildUpdate(dateText, 25, cont));
                             awm.updateAppWidget(awid, views);
                         }
                     }); 

                 }catch (InterruptedException e) {
                 }
             }
         }
     };
     t.start();
}

这会生成一个空白小部件。

我不是要代码,只是帮我找出我的错误是什么以及我应该如何处理它?

您的 Thread 方法不起作用,因为 Android 不允许未创建 View 层次结构的 Thread 接触那些 View。与大多数情况一样,您尝试从您的工作人员 Thread 更新的 View 很可能在 UI 线程上膨胀并实例化为您的 Activity 的一部分Android.

的创作过程

我想你有两个选择:

  1. 始终在 NewAppWidget 构造函数中传递 Activity 作为 Context 参数。

    然后您可以安全地将 Context 对象转换为 Activity 并调用 Activity.runOnUiThread(Runnable),或者将 Context 字段更改为 Activity以避免每次都必须投射。

  2. 使用一个Handler

    实例化你的 Handler 如下。这将创建一个链接到 UI 线程(也称为 "main" 线程)的 Handler 对象。

    Handler handler = new Handler(Looper.getMainLooper());

    然后您可以使用 Handler 到 post Runnables,它们将在您的 UI Thread 上成为 运行工人 Thread。您将能够通过您的工作人员 Thread 以这种方式更新 Views:

    handler.post(new Runnable() { ... });

我推荐第二种方法,因为它更简洁,而且您不会总是需要这样引用 Activity

请记住第二种方法,在您的 Runnable 中,您需要对要更新的 ActivityView 使用 WeakReference以防止内存泄漏。即使您的 ActivityView 被(应该)垃圾回收了,您的工作人员 Thread 可能仍处于 运行ning 状态。使用 WeakReference 允许垃圾收集器收集你的 Activity / View 即使你的工人 Thread 仍然是 运行ning.