方法必须从主线程调用,当前推断线程是worker

Method must be called from main thread,currenty inferred thread is worker

我正在尝试每 15 分钟或类似的时间更换一次 Android 的墙纸。用户可以选择时间,我是 运行 使用 Workmanager 的周期性工作。

PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(SomeWorker.class, 15, TimeUnit.MINUTES).build();
WorkManager.getInstance().enqueue(periodicWorkRequest);

我这样称呼我的工人Class。工作class是这个

public class SomeWorker extends Worker {
Context context = getApplicationContext();
private String URL;
@NonNull
@Override
public Result doWork() {
    new FetchWallpaper().execute();
    return Result.SUCCESS;
}
private class FetchWallpaper extends AsyncTask<Void, Void, Void>
{
    @Override
    protected Void doInBackground(Void... voids) {
        try
        {
            URL = "myurl.com";
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(URL)
                    .build();
            Response responses = null;
            try {
                responses = client
                        .newCall(request)
                        .execute();
                String jsonData = responses.body().string();

                JSONArray jsonArr = new JSONArray(jsonData);
                JSONObject c = jsonArr.getJSONObject(new Random().nextInt(jsonArr.length()));

                String imageUrl = c.getString("wallpaper");

                Bitmap result= Picasso.with(getApplicationContext())
                        .load(imageUrl)
                        .get();

                WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
                try {
                    wallpaperManager.setBitmap(result);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            Date currentTime = Calendar.getInstance().getTime();
        }
        catch (Exception e)
        {
            Date currentTime = Calendar.getInstance().getTime();
        }
        return null;
    }
}}

在那条特定的线上,

        new FetchWallpaper().execute();

我收到错误消息说它必须从主线程调用。我是 Android 的新手,我不知道这是否是个好方法。 如果有更好的方法来执行此类任务,请告诉我。

您无法从 doInBackground 方法更新 UI。如果你想在 UI 上做某事,你必须在 UI 主线程上做。因此,在 onPostExecute 方法中将 setBitmap 代码编写为 onPostExecute 在主 UI 线程上。

为此,将 AsyncTask 的第三个参数设置为 String

AsyncTask<Void, Void, String>

因此 return 类型的 doInBackground 方法将是 String

protected String doInBackground(Void... voids)
...
...
return imageUrl;
}

你的 onPostExecute 方法就像

@Override
protected void onPostExecute(String imageUrl) {
    super.onPostExecute(imageUrl);

 Bitmap result= Picasso.with(getApplicationContext())
                    .load(imageUrl)
                    .get();

 WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
 try {
        wallpaperManager.setBitmap(result);
      } catch (Exception ex) {
        ex.printStackTrace();
      }

}

Worker class 已经在后台线程上调用了 doWork - 您根本不需要使用 AsyncTask

只需将所有内容从您的 doInBackground 方法直接移至 Worker 的 doWork

new AsyncTask<Void, Bitmap, Bitmap>() {
    @Override
    protected Bitmap doInBackground(Void... params) {
       Bitmap bitmap = null;
       try {
           InputStream inputStream;
           inputStream = new java.net.URL(url).openStream();
           bitmap = BitmapFactory.decodeStream(inputStream);
        }catch (Exception e) {
           logAppE(TAG, "BITMAP ERROR -> " + e.getMessage());
         }
         return bitmap
      }

      @Override
      protected void onPostExecute(Bitmap s) {
        try {
            Glide.with(context).asGif().load(s).into(imgViewGIF);
        } catch (Exception e) {
              logAppE(TAG, "BITMAP -> " + e.getMessage());
         }
      }
    }.execute();