我已经开发了一些显示adapterviewflipper布局的主屏幕小部件。它们自动启动并具有3秒的翻转间隔。他们显示一个带有自定义动画进出动画的小集合(总时间为2秒)。收集数据每分钟刷新一次。
经过一段不确定的时间后,翻转间隔变得越来越大,可能需要花费约17秒的时间进行动画处理。我不明白为什么。
有android限制吗?内存泄漏问题? 如果我重新启动手机,则可以节省时间,但是不久之后我会遇到问题。
小部件布局
<AdapterViewFlipper
android:id="@+id/calendar_widget_adapterViewFlipper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:autoStart="true"
android:flipInterval="3000"
android:animateLayoutChanges="true"
android:inAnimation="@animator/slide_in_bottom"
android:outAnimation="@animator/fade_out"
/>
AppWidget Provider
@Override
public void onReceive(Context context, Intent intent) {
//Log.d(LOG_TAG, "Received intent " + intent);
switch (intent.getAction()){
case ACTION_MESSAGE_DATA_UPDATE :
ComponentName thisAppWidget = new ComponentName(context.getPackageName(), getClass().getName());
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
for (int appWidgetID: ids) {
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetID, R.id.calendar_widget_adapterViewFlipper);
}
break;
...
App Widget Provider配置文件
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="@layout/calendar_widget"
android:initialLayout="@layout/calendar_widget"
android:autoAdvanceViewId="@id/calendar_widget_adapterViewFlipper"
android:minWidth="250dp"
android:minHeight="50dp"
android:minResizeWidth="250dp"
android:minResizeHeight="50dp"
android:previewImage="@drawable/calendar_ori_portrait"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="0"
android:widgetCategory="home_screen|keyguard"></appwidget-provider>
CalendarWidgetRemoteViewsService
public class CalendarWidgetRemoteViewsService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new CalendarWidgetRemoteViewsFactory(this.getApplicationContext(), intent);
}
}
class CalendarWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private Context mContext;
private int mAppWidgetId;
private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
public CalendarWidgetRemoteViewsFactory(Context context, Intent intent) {
mContext = context;
mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
@Override
public void onCreate() {
// In onCreate() you setup any connections / cursors to your data source. Heavy lifting,
// for example downloading or creating content etc, should be deferred to onDataSetChanged()
// or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
}
@Override
public void onDataSetChanged() {
// This is triggered when you call AppWidgetManager notifyAppWidgetViewDataChanged
// on the collection view corresponding to this factory. You can do heaving lifting in
// here, synchronously. For example, if you need to process an image, fetch something
// from the network, etc., it is ok to do it here, synchronously. The widget will remain
// in its current state while work is being done here, so you don't need to worry about
// locking up the widget.
//Log.d("CWRVS", "onDataSetChanged begins");
final int[] ErrorCode = {0};
mWidgetItems.clear();
if (!UtilsHelper.isOnline(mContext)){
ErrorCode[0] = 1;
}
if (ErrorCode[0] == 0)
{
final CountDownLatch latchSignal = new CountDownLatch(1);
AuthenticationHelper authenticationHelper = AuthenticationHelper.getInstance(mContext);
authenticationHelper.acquireTokenSilentlyWithAccountCheck(new AuthenticationCallback() {
@Override
public void onSuccess(AuthenticationResult authenticationResult) {
//Log.d("AUTH", "onSuccess");
final GraphHelper graphHelper = GraphHelper.getInstance();
graphHelper.getAllCalendarsEventsSupEqToday(authenticationResult.getAccessToken(), new ICallback<List<WidgetItem>>() {
@Override
public void success(List<WidgetItem> lwi) {
mWidgetItems = lwi;
latchSignal.countDown();
}
@Override
public void failure(ClientException ex) {
//Log.e("GRAPH", "Error getting events", ex);
latchSignal.countDown();
}
});
}
@Override
public void onError(MsalException exception) {
//Log.d("AUTH", "onError");
//if ( exception.getErrorCode() == AuthenticationHelper.NO_CLIENT_ACCOUNT_REGISTERED ){
//}
ErrorCode[0] = 2;
latchSignal.countDown();
}
@Override
public void onCancel() {
//Log.d("AUTH", "onCancel");
latchSignal.countDown();
}
});
//}
try{
latchSignal.await(15, TimeUnit.SECONDS);
}
catch (InterruptedException e){
Log.e("CDN", "CountDownException", e);
}
}
//Sending BroadCast for Error
Intent ErrorIntent = new Intent(mContext, CalendarWidgetProvider.class);
ErrorIntent.setAction(CalendarWidgetProvider.ACTION_CALENDAR_DATA_PARTIAL_UPDATE);
Bundle extras = new Bundle();
extras.putInt(CalendarWidgetProvider.EXTRA_ERROR_CODE, ErrorCode[0]);
ErrorIntent.putExtras(extras);
mContext.sendBroadcast(ErrorIntent);
//Log.d("CWRVS", "onDataSetChanged ends");
}
@Override
public void onDestroy() {
// In onDestroy() you should tear down anything that was setup for your data source,
// eg. cursors, connections, etc.
mWidgetItems.clear();
}
@Override
public int getCount() {
return mWidgetItems.size();
}
@Override
public RemoteViews getViewAt(int position) {
// position will always range from 0 to getCount() - 1.
// We construct a remote views item based on our widget item xml file, and set the
//
if (this.getCount() == 0){
return null;
}
WidgetItem wi = mWidgetItems.get(position);
RemoteViews rv = wi.BuildRemoteViews(mContext, position, this.getCount());
// You can do heaving lifting in here, synchronously. For example, if you need to
// process an image, fetch something from the network, etc., it is ok to do it here,
// synchronously. A loading view will show up in lieu of the actual contents in the
// interim.
// Return the remote views object.
return rv;
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return true;
}
}
我希望flipinterval尊重其价值。
致谢