Android 带有从 AsyncTask 填充的 ListView 的小部件

Android Widget with ListView populated from AsyncTask

我正在为我的应用程序创建一个小部件,但是当我必须填充列表视图时我卡住了。我使用异步任务从我的 Web 数据库中获取每个项目,我在 WidgetDataProvider(实现 RemoteViewsService.RemoteViewsFactory)的 onCreate() 中调用它。 问题是,通常当我创建小部件时,它不会填充列表,我必须等待几秒钟才能在主屏幕上发布小部件。

如果我抓住并释放小部件,它会显示如下:empty widget

如果我等一下,它会显示为:right widget

这是我的代码:

AppWidget

public class AppWidget extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.app_widget);

    Intent intent = new Intent(context, LoginActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
    views.setOnClickPendingIntent(R.id.widget_title, pendingIntent);

    views.setRemoteAdapter(R.id.widget_listView, new Intent(context, WidgetService.class));
    appWidgetManager.updateAppWidget(appWidgetId, views);
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    super.onUpdate(context, appWidgetManager, appWidgetIds);
    for (int appWidgetId : appWidgetIds) {
        updateAppWidget(context, appWidgetManager, appWidgetId);
    }
}

@Override
public void onEnabled(Context context) {
}

@Override
public void onDisabled(Context context) {
}

}

**小部件服务**

public class WidgetService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
    return new WidgetDataRemote(this, intent);
}}

WidgetDataRemote

public class WidgetDataRemoteimplements RemoteViewsService.RemoteViewsFactory {
Context context;
Intent intent;
ArrayList<String> date = new ArrayList<>();
ArrayList<String> subj = new ArrayList<>();
ArrayList<String> type = new ArrayList<>();
ArrayList<String> comment = new ArrayList<>();
JSONParser jsonParser = new JSONParser();
ArrayList<String> subjFromDb = new ArrayList<>();
int pippo = 0;

public WidgetDataRemote(Context context, Intent intent) {
    this.context = context;
    this.intent = intent;
}

@Override
public RemoteViews getViewAt(int position) {
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.item_widget);
    remoteViews.setTextViewText(R.id.task_data, date.get(position));
    remoteViews.setTextViewText(R.id.task_subject, subj.get(position));
    remoteViews.setTextViewText(R.id.task_type, type.get(position));
    remoteViews.setTextViewText(R.id.task_comment, comment.get(position));
    return remoteViews;
}

@Override
public void onCreate() {
    new LoadSubjects().execute();
}

@Override
public void onDataSetChanged() {
}

@Override
public void onDestroy() {
    date.clear();
    subj.clear();
    type.clear();
    comment.clear();
}

@Override
public int getCount() {
    return date.size();
}

@Override
public RemoteViews getLoadingView() {
    return null;
}

@Override
public int getViewTypeCount() {
    return 1;
}

@Override
public long getItemId(int id) {
    return id;
}

@Override
public boolean hasStableIds() {
    return true;
}

class LoadSubjects extends AsyncTask<String, String, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        subjFromDb.clear();
        pippo = 0;
    }

    @Override
    protected String doInBackground(String... args) {
        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("class", User.getClasse()));
        JSONArray json = jsonParser.makeHttpRequestArray(Constants.URL_LOAD_SUBJECTS, "POST", params);
        try {
            if (!json.toString().equals("[null]")) {
                for (int i = 0; i < json.length(); i++) {
                    JSONObject c = json.getJSONObject(i);
                    String subj = c.getString(Constants.TAG_NAME);
                    subjFromDb.add(subj);
                }
            } else {
                pippo = 1;
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    protected void onPostExecute(String file_url) {
        if (pippo == 0) {
            new LoadTasks().execute();
        }
    }

    class LoadTasks extends AsyncTask<String, String, String> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pippo = 0;
        }

        @Override
        protected String doInBackground(String... args) {
            List<NameValuePair> params = new ArrayList<>();
            params.add(new BasicNameValuePair("id_class", User.getClasse()));
            JSONArray json = jsonParser.makeHttpRequestArray(Constants.URL_LOAD_TASKS, "POST", params);
            try {
                if (!json.toString().equals("[null]")) {
                    for (int i = 0; i < json.length(); i++) {
                        JSONObject c = json.getJSONObject(i);
                        Date data = null;
                        try {
                            data = new SimpleDateFormat("yyyy-MM-dd").parse(c.getString(Constants.TAG_DATE));
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                        String newDate = new SimpleDateFormat("dd/MM/yyyy").format(data);
                        if (subjFromDb.contains(c.getString(Constants.TAG_SUBJECT))) {
                            date.add(newDate);
                            subj.add(c.getString(Constants.TAG_SUBJECT));
                            type.add(c.getString(Constants.TAG_TYPE));
                            comment.add(c.getString(Constants.TAG_COMMENT));
                        }
                    }
                } else {
                    pippo = 1;
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }

        protected void onPostExecute(String file_url) {
            if (pippo == 0){
                AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                ComponentName thisWidget = new ComponentName(context, WidgetDataProvider.class);
                int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
                appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_listView);
                // I use this to update the listview after fetch data. Is it correct?
            }
        }
    }
}}

我仅使用 TimerTask 并修改 onPostExecute 中的更新过程就解决了我的问题。这是我更改的文件:

Widget DataRemote

public class WidgetDataRemote implements RemoteViewsService.RemoteViewsFactory {
final Context context;
Intent intent;
ArrayList<String> date = new ArrayList<>();
ArrayList<String> subj = new ArrayList<>();
ArrayList<String> type = new ArrayList<>();
ArrayList<String> comment = new ArrayList<>();
JSONParser jsonParser = new JSONParser();
ArrayList<String> subjFromDb = new ArrayList<>();
final Context sad;
int pippo = 0;

public WidgetDataRemote(Context context, Intent intent) {
    this.context = context;
    this.intent = intent;
    sad = context;
    final Handler handler = new Handler();
    Timer timer = new Timer();
    TimerTask doAsynchronousTask = new TimerTask() {
        @Override
        public void run() {
            handler.post(new Runnable() {
                public void run() {
                    try {
                        new LoadSubjects().execute();
                    } catch (Exception ignored) {}
                }
            });
        }
    };
    timer.schedule(doAsynchronousTask, 0, 60000);
}

@Override
public RemoteViews getViewAt(int position) {
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.item_widget);
    if(date.size()>0) {
        remoteViews.setTextViewText(R.id.task_data, date.get(position));
        remoteViews.setTextViewText(R.id.task_subject, subj.get(position));
        remoteViews.setTextViewText(R.id.task_type, type.get(position));
        remoteViews.setTextViewText(R.id.task_comment, comment.get(position));
    }else{
        remoteViews.setTextViewText(R.id.task_data, "");
        remoteViews.setTextViewText(R.id.task_subject, "loading");
        remoteViews.setTextViewText(R.id.task_type, "");
        remoteViews.setTextViewText(R.id.task_comment, "");
    }
    return remoteViews;
}

@Override
public void onCreate() {
    Toast.makeText(context, "Loading...", Toast.LENGTH_LONG).show();
}

@Override
public void onDataSetChanged() {
}

@Override
public void onDestroy() {
    date.clear();
    subj.clear();
    type.clear();
    comment.clear();
}

@Override
public int getCount() {
    return date.size();
}

@Override
public RemoteViews getLoadingView() {
    return null;
}

@Override
public int getViewTypeCount() {
    return 1;
}

@Override
public long getItemId(int id) {
    return id;
}

@Override
public boolean hasStableIds() {
    return true;
}

class LoadSubjects extends AsyncTask<String, String, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        subjFromDb.clear();
        pippo = 0;
    }

    @Override
    protected String doInBackground(String... args) {
        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("class", User.getClasse()));
        JSONArray json = jsonParser.makeHttpRequestArray(Constants.URL_LOAD_SUBJECTS, "POST", params);
        try {
            if (!json.toString().equals("[null]")) {
                for (int i = 0; i < json.length(); i++) {
                    JSONObject c = json.getJSONObject(i);
                    String subj = c.getString(Constants.TAG_NAME);
                    subjFromDb.add(subj);
                }
            } else {
                pippo = 1;
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    protected void onPostExecute(String file_url) {
        if (pippo == 0) {
            new LoadTasks().execute();
        }
    }
}

class LoadTasks extends AsyncTask<String, String, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        date.clear();
        subj.clear();
        type.clear();
        comment.clear();
        pippo = 0;
    }

    @Override
    protected String doInBackground(String... args) {
        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("id_class", User.getClasse()));
        JSONArray json = jsonParser.makeHttpRequestArray(Constants.URL_LOAD_TASKS, "POST", params);
        try {
            if (!json.toString().equals("[null]")) {
                for (int i = 0; i < json.length(); i++) {
                    JSONObject c = json.getJSONObject(i);
                    Date data = null;
                    try {
                        data = new SimpleDateFormat("yyyy-MM-dd").parse(c.getString(Constants.TAG_DATE));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    String newDate = new SimpleDateFormat("dd/MM/yyyy").format(data);
                    if (subjFromDb.contains(c.getString(Constants.TAG_SUBJECT))) {
                        date.add(newDate);
                        subj.add(c.getString(Constants.TAG_SUBJECT));
                        type.add(c.getString(Constants.TAG_TYPE));
                        comment.add(c.getString(Constants.TAG_COMMENT));
                    }
                }
            } else {
                pippo = 1;
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    protected void onPostExecute(String file_url) {
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(sad);
        appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetManager.getAppWidgetIds(new ComponentName(sad, AppWidget.class)), R.id.widget_listView);
    }
}}