我可以在AppWidgetHost
内使用Fragment
吗?我无法将大多数小部件添加到我的AppWidgetHost中进行更新。这是我的情景..
LauncherActivity.java
main.xml
CodeRedWidgetHostFragment.java
onCreateView
创建AppWidgetHost的实例& AppWidgetManager
使用我已存储在首选项
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);
}
}
}
}
答案 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()。
但是当我切换到第二个活动时,这就是造成错误的原因:
所以活动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;
}
请务必删除代码中stopListening
和startListening
的所有其他实例。