Android支持库23.4.0:android.support.v7.widget.TintContextWrapper无法强制转换为Activity

时间:2016-05-12 19:54:32

标签: android android-support-library

所以我更新到最新的支持库,并且崩溃我无法修复。我的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...
}

我有一个工作监听器,用于捕获点击并启动一个新的活动。这在支持库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,然后按钮的颜色被着色,如下所示:

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,但项目成员建议在这里询问StackOverflow,所以就在这里。

我尝试了什么?

由于Google问题中的项目成员声明了您需要从已打包的上下​​文中获取活动。我尝试转换为TintContextWrapper而不是MyActivity很好,但我无法弄清楚如何从MyActivity获取TintContextWrapper

所以我的问题是:

  1. 如何从MyActivity
  2. 获取TintContextWrapper
  3. 为什么我的ImageButton突然包裹在TintContextWrapper
  4. 这种行为真的应该被期待吗?
  5. 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)
    

7 个答案:

答案 0 :(得分:8)

  1. 活动n TintContextWRapper来自ContextWrapperContextWrapper有一个方法getBaseContext()。创建一个循环方法应该很容易,该方法检查instanceof WrapContext,获取基本上下文,然后检查instanceof Activity。 (如果你对这个方法有疑问,可以在这里评论,我将挖掘我的一些项目并粘贴到你这里)

  2. 因为AppCompat包装你的上下文以便能够注入&#34; compat&#34;观点和&#34; compat&#34;着色和其他&#34; compat&#34;东西。这是正常的。

  3. 是。这就是AppCompat如何做到这一点。

答案 1 :(得分:4)

@Krøllebølle

  

Android支持库23.4.0:   android.support.v7.widget.TintContextWrapper无法强制转换为   活性

回答你的问题是: 首先,您的点击事件代码应该是:

@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;
}

并修复了崩溃/异常:)

答案 2 :(得分:3)

我的建议是将您的活动引用传递给onClickListener以避免TintContextWrapper的问题。为您的班级提供MyActivity的参考很简单,并避免可能的投射问题。

答案 3 :(得分:1)

你可以尝试

Activity activity = (Activity) view.getRootView().getContext()

获取包含此视图的上下文,而不包含android.support.v7.widget.TintContextWrapper的包装。

答案 4 :(得分:0)

  
      
  1. 如何从TintContextWrapper获取MyActivity?
  2.   

你真的不应该。我们无法保证View的上下文将成为一个Activity - 绝对不是一个特定的Activity。你在哪里设置OnClickListener?我假设在您设置侦听器的位置,您将可以访问该活动。例如,如果您要从“活动”设置侦听器:

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);
        }
    }
}

答案 5 :(得分:0)

更新Android支持库后,它对我有用。

答案 6 :(得分:0)

我遇到了同样的问题,并以解决方法解决了 - Android支持库,修订版24。2。1(2016年9月)
- compileSdkVersion 24
- buildToolsVersion“24.0.3”