具有列表视图的 Android 小部件正在刷新具有丑陋的短“闪烁”效果的项目

Ada*_*gyi 5 android listview android-widget android-service android-listview

我想制作一个带有 ListView 的小部件,您可以在其中添加 listItems 来显示计数器计时器,以查看您有多少时间来处理某个事件。

这是我第一次使用小部件,我不知道我的方法是好还是坏,到目前为止我得到了这个:

AppWidgetProvider 用于通过启动服务的周期性事件来启动可运行程序。该服务称为 UpdateService,它正在更新数据集并刷新 listView。

好吧,我可以说它正在工作,但是每次刷新发生时,我的列表视图都会闪烁很短的时间,就像列表项消失很短的时间然后重新出现并刷新值。它非常丑陋,我想摆脱它。

我尝试将 listView 的 cacheColorHint 更改为 #00000000 但没有解决我的问题,也无法在互联网上找到任何内容。

如果可以的话请提供帮助,如果这种方法不是实现此“时间计数器列表”的最佳方法,请提供一些建议

public class WidgetProvider extends AppWidgetProvider {

static public String TAG = "widgetProvider";
static Handler handler = new Handler();
//TODO: stop runnables at widget destroying
static MyRunnable myRunnable;
static long refreshInterval = 1000 * 1;

//Runnable for refreshing my widget
class MyRunnable implements Runnable {

    Context context;

    public MyRunnable(Context context) {
        this.context = context;
    }
    public void run() {
        Log.i(TAG, "My runnable has ran!");
        context.startService(new Intent(context, UpdateService.class));
        handler.postDelayed(myRunnable, refreshInterval);
    }
}

//Service for updating the widget
public static class UpdateService extends Service {

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.i(TAG, "UpdateService - onStart()");
        int[] appWidgetIds = AppWidgetManager.getInstance(getApplicationContext()).getAppWidgetIds(new ComponentName(getApplicationContext(), WidgetProvider.class));
        int N = appWidgetIds.length;
        Log.i(TAG, "appWidgetIds.length: " + appWidgetIds.length);
        for (int i = 0; i < N; ++i) {
            //Changing dataset
            ListProvider.populateAndRefreshData();
            //Notifying the listview about the change
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
            appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.listViewWidget);
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

@Override
public void onDeleted(Context context, int[] appWidgetIds) {
    //TODO: stop runnables
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    super.onUpdate(context, appWidgetManager, appWidgetIds);

    final int N = appWidgetIds.length;

    //init each widget, then call the runnable for periodic event for counting time
    for (int i = 0; i < N; ++i) {
        RemoteViews remoteViews = updateWidgetListView(context, appWidgetIds[i]);
        appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews);
    }

    //start the runnable
    myRunnable = new MyRunnable(context);
    handler.postDelayed(myRunnable, 0);
}


private static RemoteViews updateWidgetListView(Context context, int appWidgetId) {
    Log.i(TAG, "updating a widget: " + appWidgetId);
    //which layout to show on widget
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
    //RemoteViews Service needed to provide adapter for ListView
    Intent svcIntent = new Intent(context, WidgetService.class);
    //passing app widget id to that RemoteViews Service
    svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    //setting a unique Uri to the intent
    svcIntent.setData(Uri.parse(svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
    //setting adapter to listview of the widget
    remoteViews.setRemoteAdapter(appWidgetId, R.id.listViewWidget, svcIntent);
    //setting an empty view in case of no data
    remoteViews.setEmptyView(R.id.listViewWidget, R.id.empty_view);
    return remoteViews;
}
}
Run Code Online (Sandbox Code Playgroud)

RemoteViewService用于定义适配器

public class WidgetService extends RemoteViewsService {

/*
 * Defining the Adapter of the listview here Adapter is ListProvider
 */
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {

    int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
    return (new ListProvider(this.getApplicationContext(), intent));
}
}
Run Code Online (Sandbox Code Playgroud)

适配器:

/**
 * Adapter of ListView
 * 
 */

public class ListProvider implements RemoteViewsFactory {

public static ArrayList<Record> listItemList = new ArrayList<Record>();
private Context context = null;
private int appWidgetId;

public ListProvider(Context context, Intent intent) {
    this.context = context;
    appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
    populateAndRefreshData();
}
//TODO: just test populating
public static void populateAndRefreshData() {
    listItemList = new ArrayList<Record>();
    Record record = new Record();
    record.name = DateUtils.getIntervalToDate("2015-07-01 10:00:00");
    record.content = "...";
    record.icon = R.drawable.logo_1;
    listItemList.add(record);
}
@Override
public int getCount() {
    return listItemList.size();
}
@Override
public long getItemId(int position) {
    return position;
}
/*
 * Similar to getView of Adapter where instead of Viewwe return RemoteViews
 */
@Override
public RemoteViews getViewAt(int position) {
    final RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.list_row);
    Record listItem = listItemList.get(position);
    remoteView.setTextViewText(R.id.heading, listItem.name);
    remoteView.setImageViewResource(R.id.imageView, listItem.icon);
    return remoteView;
}
@Override
public RemoteViews getLoadingView() {
    return null;
}
@Override
public int getViewTypeCount() {
    return 1;
}
@Override
public boolean hasStableIds() {
    return true;
}
@Override
public void onCreate() {}
@Override
public void onDataSetChanged() {}
@Override
public void onDestroy() {}
}
Run Code Online (Sandbox Code Playgroud)