AppWidgetHost不更新小部件

时间:2014-04-03 03:00:15

标签: android android-fragments android-widget host android-appwidget

我可以在AppWidgetHost内使用Fragment吗?我无法将大多数小部件添加到我的AppWidgetHost中进行更新。这是我的情景..

LauncherActivity.java

  • 非常简单,只需使用布局调用setContentView。

main.xml

  • 包含一些片段,包括其中包含AppWidgetHost的片段。

CodeRedWidgetHostFragment.java

  • onCreateView
     创建AppWidgetHost的实例& AppWidgetManager
     使用我已存储在首选项

  • 中的窗口小部件ID创建和设置主机视图
  • onStart()
     appWidgetHost.startListening()

  • onStop()
     appWidgetHost.stopListening()

当我获得AppWidgetHost和AppWidgetManager的实例时,我使用getActivity()来获取Fragments托管活动。我想知道这是不是我的小部件没有更新的原因?

有些小部件实际上会更新,例如模拟时钟,但是,Youtube小部件不会自动循环显示视频缩略图。

我应该提一下,我在AppWidgetHost中选择了我想要的小部件,在另一个活动中将所选小部件的ID存储在SharedPreferences中。

这是我的Fragment类的代码。

package com.brockoli.android.codered.widgethost;

import android.app.Fragment;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.brockoli.android.codered.R;

public class CodeRedWidgetHostFragment extends Fragment {
private static final String TAG = CodeRedWidgetHostFragment.class.getSimpleName();

public static final String CODERED_WIDGET_ID = "CODERED_WIDGET_ID";

private SharedPreferences mSharedPrefsWidgets;

AppWidgetManager mAppWidgetManager;
AppWidgetHost mAppWidgetHost;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View parentView = inflater.inflate(R.layout.widget_host, null);

    mSharedPrefsWidgets = getActivity().getSharedPreferences("codered_widgets", 0);

    mAppWidgetManager = AppWidgetManager.getInstance(getActivity());
    mAppWidgetHost = new AppWidgetHost(getActivity(), R.id.APPWIDGET_HOST_ID);

    createWidget(parentView);

    return parentView;
}

@Override
public void onStart() {
    super.onStart();
    mAppWidgetHost.startListening();
}

@Override
public void onStop() {
    super.onStop();
    mAppWidgetHost.stopListening();
}


@Override
public void onResume() {
    super.onResume();
    createWidget(getView());
}

/**
 * Creates the widget and adds to our view layout.
 */
public void createWidget(View v) {
    if (v != null) {
        // Remove any existing widgets from the widget host
        ((ViewGroup) v).removeAllViews();
        int appWidgetId = mSharedPrefsWidgets.getInt(CODERED_WIDGET_ID, -1);
        if (appWidgetId > -1) {
            AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
            AppWidgetHostView hostView = mAppWidgetHost.createView(getActivity(), appWidgetId, appWidgetInfo);
            hostView.setAppWidget(appWidgetId, appWidgetInfo);
            ((ViewGroup) v).addView(hostView);
            Log.i(TAG, "The widget size is: " + appWidgetInfo.minWidth + "*" + appWidgetInfo.minHeight);
        }   
    }
}
}

6 个答案:

答案 0 :(得分:1)

基于Clemens的回答,AppWidgetHost应该在应用程序的整个生命周期中保持活跃状态​​。这意味着无论Activity如何,您都应该可以在某个地方轻松访问AppWidgetHost和AppWidgetManager的实例。

public class YourApp extends Application {

    private static final int HARDCODED_ID = 0; 

    private static AppWidgetHost appWidgetHost;
    private static AppWidgetManager appWidgetManager;

    @Override
    public void onCreate() {
        super.onCreate();

        appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
        appWidgetHost = new AppWidgetHost(getApplicationContext(), HARDCODED_ID);
        appWidgetHost.startListening();
    }

    @Override
    public void onTerminate() {
        super.onTerminate();

        appWidgetHost.stopListening();
        appWidgetHost = null;
    }

    public static AppWidgetHost getAppWidgetHost() { return appWidgetHost; }

    public static AppWidgetManager getAppWidgetManager() { return appWidgetManager; }

}

我当前的实施已正确更新。测试了许多需要实时'的应用程序。像我的音乐播放器小部件更新。

请记住,应用程序上下文用于确保AppWidgetHost和AppWidgetManager的上下文始终可用。

,在其小部件中使用AppCompat库的较新小部件目前在com.android.support:appcompat-v7:23.1.1依赖项中存在错误。为避免这种情况,请在调用以下内容时使用应用程序上下文。

AppWidgetHostView hostView = YourApp.getAppWidgetHost()
            .createView(context.getApplicationContexxt(), appWidgetId, info);

答案 1 :(得分:0)

如果您的某些小部件确实更新,我相信您的getActivity()可能就是问题。

尝试在片段中创建引用,例如:

private Activity activity;

并在onAttach()

中设置它
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    this.activity = activity; 
}

这样,它应始终指向您当前的托管活动。

答案 2 :(得分:0)

我找到了问题的原因,对于那些将来会陷入困境的人来说,这里有解释:

AppwidgetManager实际上是一个系统服务,在调用AppwidgetManger.getInstance(Context context)时不会获得新实例,而是对单个实例的引用,这在其他地方(跨活动,服务......)是相同的。

AppwidgetManger来源:

public static AppWidgetManager getInstance(Context context) {
     return (AppWidgetManager) context.getSystemService(Context.APPWIDGET_SERVICE);
 }

所以对我来说,我的问题是我有两个活动,每个活动都引用了AppwidgetManager,根据文档,他们在onStart()中调用了AppwidgetManger.startListening(),在onStop()中调用了onStopListening()。

但是当我切换到第二个活动时,这就是造成错误的原因:

  • 活性1:的onPause()
  • 活性2:的onCreate()
  • Activity2:onStart() startListening()
  • Activity1:onStop() stopListening()
  • 活性1:的onDestroy()
  • 活性2:的onResume()

所以活动2正确调用startListening(),但在后台,活动1仍处于活动状态,并将stopListening()调用到同一个AppwidgetManager实例。

此外,你应该改变这个

mAppWidgetHost = new AppWidgetHost(getActivity(), R.id.APPWIDGET_HOST_ID);

mAppWidgetHost = new AppWidgetHost(getActivity().getApplicationContext(), R.id.APPWIDGET_HOST_ID);

它会阻止系统继续引用您的活动并使其远离GC(传递活动会造成内存泄漏)

答案 3 :(得分:0)

我遇到了同样的问题而且我还没有解决它,但它似乎是AppWidgetHost的一个问题。在我的情况下,我让它工作的唯一方法是禁用stopListening()或在AppWidgetHostViews的新实例中重新创建AppWidgetHost ... 在您的情况下,可能有助于在mAppWidgetHost(或甚至onStart())中重新创建onResume() ...

答案 4 :(得分:0)

执行ViewGroup.removeAllViews()后,您应该从parentView致电mAppWidgetHost.stopListening()

答案 5 :(得分:0)

由于您正在编写启动器,我建议您查看official Android Launcher对比文档,它使用以下机制:

@Override
protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate();
    // ...
    appWidgetManager = AppWidgetManager.getInstance(this);
    appWidgetHost = new AppWidgetHost(this, HOST_WIDGET_ID);
    appWidgetHost.startListening();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    // ...
    appWidgetHost.stopListening();
    appWidgetHost = null;
}

请务必删除代码中stopListeningstartListening的所有其他实例。