【问题标题】:How can I fix android button in Android Studio, throwing cast exception?如何修复 Android Studio 中的 android 按钮,引发强制转换异常?
【发布时间】:2017-06-26 13:59:51
【问题描述】:

在我开始单击一个特定按钮 rate-button 之前,我的应用程序运行良好。每次单击此按钮时,应用程序都会崩溃,并且我会在 log cat 中收到此消息:

22808/com.nileworx.guesstheplace E/AndroidRuntime: FATAL EXCEPTION: main
                                                                        Process: com.nileworx.guesstheplace, PID: 22808
                                                                        java.lang.ClassCastException: com.nileworx.guesstheplace.GameActivity cannot be cast to com.nileworx.guesstheplace.MainActivity
                                                                            at com.nileworx.guesstheplace.CustomDialog$11.onClick(CustomDialog.java:283)
                                                                            at android.view.View.performClick(View.java:5198)
                                                                            at android.view.View$PerformClick.run(View.java:21147)
                                                                            at android.os.Handler.handleCallback(Handler.java:739)
                                                                            at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                            at android.os.Looper.loop(Looper.java:148)
                                                                            at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                            at java.lang.reflect.Method.invoke(Native Method)
                                                                            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
06-25 06:46:03.423 1642-2032/system_process W/ActivityManager:   Force finishing activity com.nileworx.guesstheplace/.GameActivity

我相信gameactivity有问题,只有一个错误:

@Override
protected void onResume() {
    super.onResume();

    if (!mSharedPreferences.getString("placesNum", "0").equals("0")) {
        String updatesDlgMsg = String.format(getResources().getString(R.string.updatesDlg), mSharedPreferences.getString("placesNum", "0"));
        dialog.showDialog(R.layout.blue_dialog, "updatesDlg", updatesDlgMsg, mSharedPreferences.getString("placesJSON", ""));
        e.putString("placesNum", "0");
        e.commit();
    }
}

第 6 行代码,出现如下信息的问题:

格式字符串“updatesDlg”不是一个有效的格式字符串,所以它应该 不传递给 String.format less... (Ctrl+F1) 如果字符串包含 '%' 字符,则该字符串可能是一个格式化字符串,它将 从 Java 代码传递给 String.format 以替换每个 '%' 发生具有特定值。此 lint 警告检查两个 相关问题:(1)格式化字符串无效,含义 那个 String.format 会在运行时抛出异常 使用格式字符串。 (2) 包含 '%' 的字符串不是 格式化字符串被传递给 String.format 调用。在这个 如果需要将“%”转义为“%%”。注意:并非所有字符串 看起来像格式化字符串是供使用的 字符串.格式;例如,它们可能包含旨在用于 android.text.format.Time#format()。林特不能总是弄清楚 字符串是日期格式,因此您可能会收到错误警告 情景。有关如何执行的信息,请参阅抑制帮助主题 在这种情况下抑制错误

我不知道如何解决这个问题,我已经尝试了 2 个多小时来解决它。

我的评分按钮代码

private void rateDlg(final Dialog dialog, final String marketLink) {

    Button rateBtn = (Button) dialog.findViewById(R.id.rateBtn);
    // if button is clicked, close the custom dialog
    rateBtn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            sou.playSound(R.raw.buttons);
            dialog.dismiss();
            MainActivity mainAct = (MainActivity) context;
            Intent intent = new Intent(Intent.ACTION_VIEW);



            intent.setData(Uri.parse("playstorelink, changed for stackoverflow"));

            if (!mainAct.MyStartActivity(intent)) {
                // Market (Google play) app seems not
                // installed, let's try
                // to open a webbrowser
                intent.setData(Uri.parse("playstorelink, changed for stackoverflow"));
                if (!mainAct.MyStartActivity(intent)) {
                    // Well if this also fails, we have run
                    // out of options,
                    // inform the user.
                    Toast.makeText(context, "Could not open Android market, please install the market app.", Toast.LENGTH_SHORT).show();
                } else {
                    editor.putInt("usingNum", 100);
                    editor.commit();
                }
            } else {
                editor.putInt("usingNum", 100);
                editor.commit();
            }
        }
    });

    Button laterBtn = (Button) dialog.findViewById(R.id.laterBtn);
    // if button is clicked, close the custom dialog
    laterBtn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            sou.playSound(R.raw.buttons);
            editor.putInt("usingNum", 0);
            editor.commit();
            dialog.dismiss();
        }
    });
}

【问题讨论】:

  • 也许你应该发布rateButton的代码。
  • 这是我得到的消息,当我滚动到第二个代码的第 6 行代码时
  • 请不要关闭问题,因此,具有有效答案的问题被认为对社区有益,因为这可能会帮助其他人。如果它解决了您的问题,请接受答案。谢谢!
  • 不要关闭问题,如果它有助于解决您的问题,请接受我的回答,或者将其作为资源开放给其他人...

标签: android button casting


【解决方案1】:

首先检查您的字符串资源文件中是否存在R.string.updatesDlg

您的另一个问题是由于错误GameActivity cannot be cast to com.nileworx.guesstheplace.MainActivity 所述的错误转换,您正在尝试将一个类转换为另一个类。您的按钮对话框代码在这里显示...

MainActivity mainAct = (MainActivity) context;

我很确定 context 在这种情况下不是 MainActivity 类型。检查context 的类型。错误表明它的类型为GameActivity

话虽如此,我不明白您为什么需要联系MainActivity,除非那里发生了特殊情况。您可以创建一个Helper 类并包含一个检查是否安装了包的方法。您在活动的上下文中传递。像这样:

//MainActivity mainAct = (MainActivity) context;
//Intent intent = new Intent(Intent.ACTION_VIEW);
//intent.setData(Uri.parse("playstorelink, changed for stackoverflow"));

if (!isPackageInstalled(playstorelink)) {
    // Market (Google play) app seems not
    // installed, let's try
    // to open a webbrowser
    //intent.setData(Uri.parse("playstorelink, changed for stackoverflow"));
    if (!isPackageInstalled(playstorelink)) {
        Toast.makeText(context, "Could not open Android market, please install the market app.", Toast.LENGTH_SHORT).show();
    } else {
        editor.putInt("usingNum", 100);
        editor.commit();
    }
} else {
    editor.putInt("usingNum", 100);
    editor.commit();
}

private boolean isPackageInstalled(Context context, String packagename) {
    try {
        context.packageManager.getPackageInfo(packagename, 0);
        return true;
    } catch (NameNotFoundException e) {
        return false;
    }
}

顺便说一句,这行代码让我相信您已将活动的实例保存到静态变量中:

if (!mainAct.MyStartActivity(intent)) {

这很糟糕!我会引用这个answer -

永远不要将上下文存储在硬引用中。否则你会泄漏 记忆。一个活动引用了 View 和许多其他的 事物。如果您存储上下文,您将存储活动并且 事情从那里开始变糟。学习传递上下文,使用 尽可能的应用程序上下文,如果你需要传递它 周围,​​这样做有很好的理由。大多数时候是 App 上下文 足以获取资源、字符串等。如果你要 存储上下文,始终存储 context.getApplicationContext();绝不 存储静态活动上下文。你也可以用谷歌搜索 StackOverflow 有一些很好的答案。

您可以使用事件系统库(例如EventBus)在活动/片段之间进行通信,而不是将上下文存储在静态变量中。您也可以将上下文从一个地方传递到另一个地方,或者使用意图putExtras 将数据添加到意图,然后在另一个活动/对话框中接收它......

【讨论】:

  • 好的,那我怎么改最后一件事,让context和mainactivity是同一个类型呢?我不擅长使用 Android Studio。
  • 什么是mainAct,是不是像public static MainActivity mainAct;这样的东西?
  • context 变量的类型是什么?如果您可以发布整个活动替换您为按钮发布的代码
  • 是的,实际上是
  • @Raven 那么我更新的答案会帮助你,这样做是非常糟糕的。我知道,因为当我开始使用 Android 时,我也做了同样的事情。永远不要将活动引用、上下文或任何类似的东西存储在静态变量中。我会用推荐更新我的答案。
猜你喜欢
  • 2021-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多