Android 支持库 23.4.0:android.support.v7.widget.TintContextWrapper 无法转换为 Activity
Android support library 23.4.0: android.support.v7.widget.TintContextWrapper cannot be cast to Activity
所以我更新到最新的支持库,但遇到了无法修复的崩溃。我的 build.gradle 现在有这些依赖项:
dependencies {
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:gridlayout-v7:23.4.0'
compile 'com.android.support:support-v4:23.4.0'
compile 'com.android.support:cardview-v7:23.4.0'
compile 'com.android.support:recyclerview-v7:23.4.0'
compile 'com.android.support:design:23.4.0'
// More stuff...
}
我有一个工作侦听器,用于捕获点击并启动新的 Activity。这在支持库 v. 23.1.0 中运行良好,但在 23.4.0(和 23.3.0)中运行不佳:
public class IngredientItemOnClickListener implements OnClickListener
{
private Ingredient mIngredient;
public IngredientItemOnClickListener(Ingredient ingredient)
{
mIngredient= ingredient;
}
@Override
public void onClick(View view)
{
MyActivity myActivity = (MyActivity) view.getContext(); // <-- crash here
myActivity.showIngredientActivity(mIngredient);
}
}
这个侦听器只是附加到一个 ImageButton
,然后 Button 的颜色被着色,如下所示:
Ingredient ingredient = getIngredient();
myImageButton.setOnClickListener(new IngredientItemOnClickListener(ingredient));
Drawable drawable = Tinting.tint(myActivity, R.drawable.my_icon, R.color.red);
myImageButton.setImageDrawable(drawable);
其中 Tinting.tint()
是我自己的着色函数:
public class Tinting
{
@Nullable
public static Drawable tint(Context context, int drawableId, int colorId)
{
final Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (drawable != null)
{
final Drawable wrapped = DrawableCompat.wrap(drawable);
drawable.mutate();
DrawableCompat.setTint(wrapped, ContextCompat.getColor(context, colorId));
}
return drawable;
}
}
以前,当我单击按钮时,一切都按预期工作,但现在视图的上下文似乎已更改为 TintContextWrapper
,我几乎找不到相关信息。我找到了 this issue,但是项目成员建议在 Whosebug 上问这里,所以在这里。
我尝试了什么?
由于 Google 问题中的项目成员指出 您需要从包装的上下文中获取 activity。 我尝试转换为 TintContextWrapper
而不是 MyActivity
,效果很好,但我无法弄清楚如何从 TintContextWrapper
.
获取 MyActivity
所以我的问题是:
- 如何从
TintContextWrapper
中获取 MyActivity
?
- 为什么我的
ImageButton
突然被TintContextWrapper
包裹了。
- 真的应该预料到这种行为吗?
xml中ImageButton的定义很简单:
<ImageButton
android:id="@+id/my_id"
android:src="@drawable/my_icon" />
堆栈跟踪:
java.lang.ClassCastException: android.support.v7.widget.TintContextWrapper cannot be cast to com.my.app.activities.MyActivity
at com.my.app.listeners.IngredientItemOnClickListener.onClick(IngredientItemOnClickListener.java:21)
at android.view.View.performClick(View.java:4475)
at android.view.View$PerformClick.run(View.java:18786)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
两者都activity n TintContextWRapper 来自ContextWrapper
。 ContextWrapper
有一个方法 getBaseContext()
。创建一个检查 instanceof WrapContext
、获取基本上下文然后检查 instanceof Activity
的循环方法应该很容易。 (如果您对此方法有疑问,请在此处评论,我将挖掘我的一些项目并粘贴到此处)
因为 AppCompat 包装了您的上下文,以便能够注入 "compat" 视图和 "compat" 着色以及其他 "compat" 东西。这很正常。
是的。这就是 AppCompat 的工作方式。
- How can I get MyActivity from the TintContextWrapper?
你真的不应该。无法保证视图的上下文将是 Activity——绝对不是特定的 Activity。你在哪里设置你的 OnClickListener?我假设在设置侦听器的地方,您可以访问 Activity。例如,如果您从 Activity:
设置侦听器
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.ingredientButton).setOnClickListener(
new IngredientItemOnClickListener(yourIngredient));
}
void showIngredientActivity(Ingredient ingredient) {
// Do your stuff
}
public class IngredientItemOnClickListener implements OnClickListener {
private Ingredient mIngredient;
public IngredientItemOnClickListener(Ingredient ingredient) {
mIngredient = ingredient;
}
@Override
public void onClick(View view) {
showIngredientActivity(mIngredient);
}
}
}
更新 Android 支持库后它对我有用。
我的建议是将您的 activity 的引用传递给 onClickListener 以避免 TintContextWrapper
的问题。为您的 class 提供对 MyActivity
的引用很简单,并且可以避免可能出现的转换问题。
我遇到了同样的问题并已通过
解决
- Android 支持库,修订版 24.2.1(2016 年 9 月)
- compileSdkVersion 24
- buildToolsVersion“24.0.3”
@Krøllebølle
Android support library 23.4.0:
android.support.v7.widget.TintContextWrapper cannot be cast to
Activity
你问题的答案是:
首先你的点击事件代码应该是这样的:
@Override
public void onClick(View view)
{
MyActivity myActivity = getRequiredActivity(view);
myActivity.showIngredientActivity(mIngredient);
}
然后写函数getRequiredActivity():
private Activity getRequiredActivity(View req_view) {
Context context = req_view.getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity)context;
}
context = ((ContextWrapper)context).getBaseContext();
}
return null;
}
并且您的 Crash/Exception 已修复 :)
你可以试试
Activity activity = (Activity) view.getRootView().getContext()
获取包含此视图的上下文,不包含 android.support.v7.widget.TintContextWrapper.
的包装器
所以我更新到最新的支持库,但遇到了无法修复的崩溃。我的 build.gradle 现在有这些依赖项:
dependencies {
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:gridlayout-v7:23.4.0'
compile 'com.android.support:support-v4:23.4.0'
compile 'com.android.support:cardview-v7:23.4.0'
compile 'com.android.support:recyclerview-v7:23.4.0'
compile 'com.android.support:design:23.4.0'
// More stuff...
}
我有一个工作侦听器,用于捕获点击并启动新的 Activity。这在支持库 v. 23.1.0 中运行良好,但在 23.4.0(和 23.3.0)中运行不佳:
public class IngredientItemOnClickListener implements OnClickListener
{
private Ingredient mIngredient;
public IngredientItemOnClickListener(Ingredient ingredient)
{
mIngredient= ingredient;
}
@Override
public void onClick(View view)
{
MyActivity myActivity = (MyActivity) view.getContext(); // <-- crash here
myActivity.showIngredientActivity(mIngredient);
}
}
这个侦听器只是附加到一个 ImageButton
,然后 Button 的颜色被着色,如下所示:
Ingredient ingredient = getIngredient();
myImageButton.setOnClickListener(new IngredientItemOnClickListener(ingredient));
Drawable drawable = Tinting.tint(myActivity, R.drawable.my_icon, R.color.red);
myImageButton.setImageDrawable(drawable);
其中 Tinting.tint()
是我自己的着色函数:
public class Tinting
{
@Nullable
public static Drawable tint(Context context, int drawableId, int colorId)
{
final Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (drawable != null)
{
final Drawable wrapped = DrawableCompat.wrap(drawable);
drawable.mutate();
DrawableCompat.setTint(wrapped, ContextCompat.getColor(context, colorId));
}
return drawable;
}
}
以前,当我单击按钮时,一切都按预期工作,但现在视图的上下文似乎已更改为 TintContextWrapper
,我几乎找不到相关信息。我找到了 this issue,但是项目成员建议在 Whosebug 上问这里,所以在这里。
我尝试了什么?
由于 Google 问题中的项目成员指出 您需要从包装的上下文中获取 activity。 我尝试转换为 TintContextWrapper
而不是 MyActivity
,效果很好,但我无法弄清楚如何从 TintContextWrapper
.
MyActivity
所以我的问题是:
- 如何从
TintContextWrapper
中获取MyActivity
? - 为什么我的
ImageButton
突然被TintContextWrapper
包裹了。 - 真的应该预料到这种行为吗?
xml中ImageButton的定义很简单:
<ImageButton
android:id="@+id/my_id"
android:src="@drawable/my_icon" />
堆栈跟踪:
java.lang.ClassCastException: android.support.v7.widget.TintContextWrapper cannot be cast to com.my.app.activities.MyActivity
at com.my.app.listeners.IngredientItemOnClickListener.onClick(IngredientItemOnClickListener.java:21)
at android.view.View.performClick(View.java:4475)
at android.view.View$PerformClick.run(View.java:18786)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
两者都activity n TintContextWRapper 来自
ContextWrapper
。ContextWrapper
有一个方法getBaseContext()
。创建一个检查instanceof WrapContext
、获取基本上下文然后检查instanceof Activity
的循环方法应该很容易。 (如果您对此方法有疑问,请在此处评论,我将挖掘我的一些项目并粘贴到此处)因为 AppCompat 包装了您的上下文,以便能够注入 "compat" 视图和 "compat" 着色以及其他 "compat" 东西。这很正常。
是的。这就是 AppCompat 的工作方式。
- How can I get MyActivity from the TintContextWrapper?
你真的不应该。无法保证视图的上下文将是 Activity——绝对不是特定的 Activity。你在哪里设置你的 OnClickListener?我假设在设置侦听器的地方,您可以访问 Activity。例如,如果您从 Activity:
设置侦听器public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.ingredientButton).setOnClickListener(
new IngredientItemOnClickListener(yourIngredient));
}
void showIngredientActivity(Ingredient ingredient) {
// Do your stuff
}
public class IngredientItemOnClickListener implements OnClickListener {
private Ingredient mIngredient;
public IngredientItemOnClickListener(Ingredient ingredient) {
mIngredient = ingredient;
}
@Override
public void onClick(View view) {
showIngredientActivity(mIngredient);
}
}
}
更新 Android 支持库后它对我有用。
我的建议是将您的 activity 的引用传递给 onClickListener 以避免 TintContextWrapper
的问题。为您的 class 提供对 MyActivity
的引用很简单,并且可以避免可能出现的转换问题。
我遇到了同样的问题并已通过
解决
- Android 支持库,修订版 24.2.1(2016 年 9 月)
- compileSdkVersion 24
- buildToolsVersion“24.0.3”
@Krøllebølle
Android support library 23.4.0: android.support.v7.widget.TintContextWrapper cannot be cast to Activity
你问题的答案是: 首先你的点击事件代码应该是这样的:
@Override
public void onClick(View view)
{
MyActivity myActivity = getRequiredActivity(view);
myActivity.showIngredientActivity(mIngredient);
}
然后写函数getRequiredActivity():
private Activity getRequiredActivity(View req_view) {
Context context = req_view.getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity)context;
}
context = ((ContextWrapper)context).getBaseContext();
}
return null;
}
并且您的 Crash/Exception 已修复 :)
你可以试试
Activity activity = (Activity) view.getRootView().getContext()
获取包含此视图的上下文,不包含 android.support.v7.widget.TintContextWrapper.
的包装器