java - 将 Activity 上下文转换为接口(interface)会抛出 ClassCastException

标签 java android classcastexception

我创建了一个类LocationFinder来获取用户的位置。

我正在实例化类和类并调用所需的方法来获取位置。

现在,在 LocationFinder 类中找到位置后,我想与我的 MainActivity 进行通信,以便我可以在某些 TextView 上更新用户的位置。

为此,我这样做了:

我的 LocationFinder 类的构造函数如下所示:

private Context context;
private OnLocationFoundListener onLocationFoundListener;

public LocationFinder(Context context) {
    this.context = context;
    onLocationFoundListener = (OnLocationFoundListener) context; // here is the exception is thrown
}

其中 OnLocationFoundListener 是一个类似以下的接口(interface):

public interface OnLocationFoundListener
{
    void setOnLocationFoundListener(String cityName, String stateName, String countryName);
}

在成功定位后,我正在使用 onLocationFoundListener.setOnLocationFoundListener(cityName, stateName, CountryName); 来通知 MainActivity 我正在其中实现 OnLocationFoundListener 并重写所需的方法。

代码示例是:

LocationFinder 类:

public class LocationFinder implements LocationListener {

    private Context context;
    private OnLocationFoundListener onLocationFoundListener;

    public LocationFinder(Context context) {
        this.context = context;
        onLocationFoundListener = (OnLocationFoundListener) context;
    }

    private static final int MY_PERMISSIONS_ACCESS_FINE_LOCATION = 1;

    private LocationManager locationManager;
    private ProgressDialog progressDialog;


    void getCityByLocation() {
        locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);

        if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale((Activity)context,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {
                // Explanation not needed, since user requests this himself

            } else {
                ActivityCompat.requestPermissions((Activity)context,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_ACCESS_FINE_LOCATION);
            }

        } else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) ||
                locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            progressDialog = new ProgressDialog(context);
            progressDialog.setMessage(context.getString(R.string.getting_location));
            progressDialog.setCancelable(false);
            progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.dialog_cancel), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    try {
                        locationManager.removeUpdates(LocationFinder.this);
                    } catch (SecurityException e) {
                        e.printStackTrace();
                    }
                }
            });
            progressDialog.show();
            if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
            }
            if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
            }
        } else {
            showLocationSettingsDialog();
        }
    }




    @Override
    public void onLocationChanged(Location location) {

        progressDialog.hide();
        try {
            locationManager.removeUpdates(this);
        } catch (SecurityException e) {
            Log.e("LocationManager", "Error while trying to stop listening for location updates. This is probably a permissions issue", e);
        }
        Log.i("LOCATION (" + location.getProvider().toUpperCase() + ")", location.getLatitude() + ", " + location.getLongitude());
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        getCityDetails(latitude, longitude);

    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {

    }

    @Override
    public void onProviderEnabled(String s) {

    }

    @Override
    public void onProviderDisabled(String s) {

    }

    private void getCityDetails(double lat, double lon)
    {
        Geocoder geocoder = new Geocoder(context, Locale.getDefault());
        List<Address> addresses = null;
        try {
            addresses = geocoder.getFromLocation(lat, lon, 1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String cityName = addresses.get(0).getAddressLine(0);
        String stateName = addresses.get(0).getAddressLine(1);
        String countryName = addresses.get(0).getAddressLine(2);

        progressDialog.dismiss();
        onLocationFoundListener.setOnLocationFoundListener(cityName, stateName, countryName);

    }

    private void showLocationSettingsDialog() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
        alertDialog.setTitle(R.string.location_settings);
        alertDialog.setMessage(R.string.location_settings_message);
        alertDialog.setPositiveButton(R.string.location_settings_button, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                context.startActivity(intent);
            }
        });
        alertDialog.setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
        alertDialog.show();
    }

    public interface OnLocationFoundListener
    {
        void setOnLocationFoundListener(String cityName, String stateName, String countryName);
    }
}

主要 Activity :

public class MainActivity extends AppCompatActivity implements LocationFinder.OnLocationFoundListener {

    Button getCurrentLocation;
    TextView locationTextview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getCurrentLocation = (Button) findViewById(R.id.getCurrentCity);
        locationTextview = (TextView) findViewById(R.id.current_city);

        LocationFinder locationFinder = new LocationFinder(getApplicationContext());
        locationFinder.getCityByLocation();

    }

    @Override
    public void setOnLocationFoundListener(String cityName, String stateName, String countryName) {
        locationTextview.setText("City : "+cityName+", "+"\nState : "+stateName+", "+"\nCountry : "+countryName);
    }
}

日志猫:

Process: com.amitupadhyay.citybasedlocation, PID: 18474
                                                                                    java.lang.RuntimeException: Unable to start activity

ComponentInfo{com.amitupadhyay.citybasedlocation/com.amitupadhyay.citybasedlocation.MainActivity}: java.lang.ClassCastException: android.app.Application cannot be cast to com.amitupadhyay.citybasedlocation.LocationFinder$OnLocationFoundListener at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2456) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2523) at android.app.ActivityThread.access$900(ActivityThread.java:168) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5609) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.amitupadhyay.citybasedlocation.LocationFinder$OnLocationFoundListener at com.amitupadhyay.citybasedlocation.LocationFinder.(LocationFinder.java:38) at com.amitupadhyay.citybasedlocation.MainActivity.onCreate(MainActivity.java:21) at android.app.Activity.performCreate(Activity.java:6307) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2409) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2523)  at android.app.ActivityThread.access$900(ActivityThread.java:168)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:148)  at android.app.ActivityThread.main(ActivityThread.java:5609)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)

我不明白为什么会发生这种情况?

最佳答案

尝试将其作为上下文而不是应用程序上下文传递。

 LocationFinder locationFinder = new LocationFinder(this);
            locationFinder.getCityByLocation();

编辑 这正是您的 logcat 所说的。您正在尝试将应用程序上下文传递给 Activity 。

关于java - 将 Activity 上下文转换为接口(interface)会抛出 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42834878/

相关文章:

Java 逻辑 - while 循环中发生的奇怪事情

安卓、wifi主动扫描

java - ClassCastException 从子类型到父类(super class)型(在 scala 中)

java - Linux 上的符号链接(symbolic link)后面的 Tomcat 缓存文件

android - 我应该使用哪种服务器型号? SQlite 还是 MySql?

java - 追加对象 OutputStream 时发生 ClassCastException

java - 从列表 <Map<String,Object>> 创建 HashMap<String,Map> 给出 java.lang.ClassCastException

java - 使用 Javamail 将图像直接插入 HTML 模板

java - 如何将LinkedList中具有多种行为的行为显示在一行中

java - 如何在启动时将数据写入文件