【问题标题】:NullPointer with Geocoder/AsyncTask - AndroidNullPointer 与 Geocoder/AsyncTask - Android
【发布时间】:2014-12-30 06:57:14
【问题描述】:

我有看起来应该很容易找到的东西,但我正在查看我的所有变量,但找不到空值。我最近将MyGeocoderTask 类从LocationMain 中分离出来,这可能是我搞砸的地方。它以前工作得很好。 :( 现在,当我单击激活findThroughPopup() 的按钮时,应用程序崩溃了。我仍然不完全擅长在需要时将变量转移到其他类,所以除了找到哪个为空之外,我可能应该有帮助编码也正确。下面是我的两个类和堆栈跟踪。感谢您的帮助。

LocationMain.java

package org.azurespot.practiceapp.location;

import org.azurespot.practiceapp.R;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.FrameLayout;

import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class LocationMain extends Activity {

    public static FragmentManager fragmentManager;
    public final int RQS_GooglePlayServices = 1;

    protected static Double latitude;
    protected static Double longitude;
    protected static Context context;
    protected static EditText addressInput;

    protected LatLng myPosition;


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

        fragmentManager = getFragmentManager();

    }

    // locates the user's location
    public void findMe(View v){

        if (LocationFragment.mMap == null){
            LocationFragment.setUpMapIfNeeded();
        }

        if (LocationFragment.mMap != null) {

        // Enabling MyLocation Layer of Google Map
        LocationFragment.mMap.setMyLocationEnabled(true);   

        // Getting LocationManager object from System Service LOCATION_SERVICE
        LocationManager locationManager = (LocationManager) 
                                        getSystemService(LOCATION_SERVICE);

        // Creating a criteria object to retrieve provider
        Criteria criteria = new Criteria();

        // Getting the name of the best provider
        String provider = locationManager.getBestProvider(criteria, true);

        // Getting Current Location
        Location location = locationManager.getLastKnownLocation(provider);
        latitude = location.getLatitude();
        longitude = location.getLongitude();

        // Creating a LatLng object for the current location
        myPosition = new LatLng(latitude, longitude);

        LocationFragment.mMap.addMarker(new MarkerOptions().position
                                                (myPosition).title("Start"));

        // For zooming automatically to the Dropped PIN Location
        LocationFragment.mMap.animateCamera(CameraUpdateFactory.newLatLngZoom
                (new LatLng(latitude, longitude), 12.0f));
        }
    }

    // enter address of your choosing into the Dialog box
    public void findThroughPopup(View v) {

        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        // set title
        builder.setTitle("Enter an address");

        // set EditText into your dialog box layout, using FrameLayout
        final FrameLayout frameView = new FrameLayout(this);
        builder.setView(frameView);
        // must inflate EditText separately
        AlertDialog alertDialog = builder.create();
        LayoutInflater inflater = alertDialog.getLayoutInflater();
        View etView = inflater.inflate(R.layout.alert_dialog_edit_text, frameView);
        // initialize EditText, use etView to pull from its specific XML
        addressInput = (EditText)etView.findViewById(R.id.address_field);

        // set Find button that finds address by showing on map
        builder.setPositiveButton("Find", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog,int id) {

                // go through map setup if needed, otherwise process address input
                if (LocationFragment.mMap == null){

                    LocationFragment.setUpMapIfNeeded();
                }

                if (LocationFragment.mMap != null) {

                    String userLocale = addressInput.getText().toString();
                    if(userLocale!=null && !userLocale.equals("")){
                        new MyGeocoderTask().execute(userLocale); 
                    }
                }
                // zooms in to wherever you map ends up,
                // the 15f is in a range of 2.0 - 21.0
                CameraUpdate camZoom = CameraUpdateFactory.zoomTo(12f);
                LocationFragment.mMap.animateCamera(camZoom);
            }
        });

        // set Cancel button
        builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog,int id) {
                // if this button is clicked, just close
                // the dialog box and do nothing
                dialog.cancel();
            }
        });

        // put all your builders in one create command
        alertDialog = builder.create();

        // show the dialog box
        alertDialog.show();

    } // end findThroughPopup()

    // resets map when back button is pressed
     @Override
        public void onBackPressed()
        {
            super.onBackPressed();
            LocationFragment.onBackPressed();
        }
}

MyGeocoderTask.java

package org.azurespot.practiceapp.location;

import java.io.IOException;
import java.util.List;

import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

/***An AsyncTask class for accessing the GeoCoding Web Service****/

public class MyGeocoderTask extends AsyncTask<String, Void, List<Address>>{

    protected LatLng enteredAddress;
    protected MarkerOptions markerOptions;


    @Override
    protected List<Address> doInBackground(String... locationName) {
        // Creating an instance of Geocoder class
        Geocoder geocoder = new Geocoder(LocationMain.context);
        List<Address> addresses = null;

        try {
            // Getting a maximum of 3 Address that matches the input text
            addresses = geocoder.getFromLocationName(locationName[0], 3);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return addresses;
    }

    // part of the GeocoderTask life cycle
    @Override
    protected void onPostExecute(List<Address> addresses) {

        if(addresses==null || addresses.size()==0){
            Toast.makeText(LocationMain.context, "No Location found", 
                                            Toast.LENGTH_SHORT).show();
        }

        // Clears all the existing markers on the map
        LocationFragment.mMap.clear();

        // Adding Markers on Google Map for each matching address
        for(int i=0;i<addresses.size();i++){

            Address address = (Address) addresses.get(i);

            // Creating an instance of GeoPoint, to display in Google Map
            enteredAddress = new LatLng(address.getLatitude(), address.getLongitude());

            String addressText = String.format("%s, %s",
            address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
            address.getCountryName());

            markerOptions = new MarkerOptions();
            markerOptions.position(enteredAddress);
            markerOptions.title(addressText);

            LocationFragment.mMap.addMarker(markerOptions);

            // Locate the first location
            if(i==0)
                LocationFragment.mMap.animateCamera
                        (CameraUpdateFactory.newLatLng(enteredAddress));
        }
    }
}

Logcat

12-29 22:55:00.444: D/AbsListView(20174): unregisterIRListener() is called 
12-29 22:55:06.154: W/dalvikvm(20174): threadid=24: thread exiting with uncaught exception (group=0x41737da0)
12-29 22:55:06.154: E/AndroidRuntime(20174): FATAL EXCEPTION: AsyncTask #1
12-29 22:55:06.154: E/AndroidRuntime(20174): Process: org.azurespot.practiceapp, PID: 20174
12-29 22:55:06.154: E/AndroidRuntime(20174): java.lang.RuntimeException: An error occured while executing doInBackground()
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.os.AsyncTask$3.done(AsyncTask.java:300)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.lang.Thread.run(Thread.java:841)
12-29 22:55:06.154: E/AndroidRuntime(20174): Caused by: java.lang.NullPointerException
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.location.GeocoderParams.<init>(GeocoderParams.java:50)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.location.Geocoder.<init>(Geocoder.java:83)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.location.Geocoder.<init>(Geocoder.java:95)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at org.azurespot.practiceapp.location.MyGeocoderTask.doInBackground(MyGeocoderTask.java:26)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at org.azurespot.practiceapp.location.MyGeocoderTask.doInBackground(MyGeocoderTask.java:1)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.os.AsyncTask$2.call(AsyncTask.java:288)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
12-29 22:55:06.154: E/AndroidRuntime(20174):    ... 4 more
12-29 22:55:06.164: D/AbsListView(20174): unregisterIRListener() is called 
12-29 22:55:06.164: E/ViewRootImpl(20174): sendUserActionEvent() mView == null
12-29 22:55:06.374: D/AbsListView(20174): unregisterIRListener() is called 
12-29 22:55:06.784: D/AbsListView(20174): onDetachedFromWindow
12-29 22:55:06.784: D/AbsListView(20174): unregisterIRListener() is called 
12-29 22:55:07.524: I/Process(20174): Sending signal. PID: 20174 SIG: 9

【问题讨论】:

    标签: android android-asynctask google-geocoder


    【解决方案1】:

    根据您的代码,MyGeocoderTask 中可能是 LocationMain.context=null

    所以你可能会像这样在MyGeocoderTask 中将上下文作为Constructor 传递

    private Context mainContxt;
    
    public MyGeocoderTask(Context con){
    mainContxt=com;
    } 
    

    和使用一样

     Geocoder geocoder = new Geocoder(mainContxt);
    

    并从Activity 打来电话

     new MyGeocoderTask(your_Activity.this).execute(userLocale); 
    

    更新:

     new MyGeocoderTask(getApplicationContext()).execute(userLocale); 
    

    【讨论】:

    • 感谢 MD,我尝试了您的建议,但仍然遇到同样的错误。它很可能与上下文有关,因为当MyGeocoderTask 仍在LocationMain 内部时,它使用getBaseContext() 代替,一旦我把它放在它自己的类中,我就改变了它,但这只是因为它有一个上面有红色错误,我真的不知道要改成什么,所以用什么代替context都是猜测。
    • @NoniA。试试getApplicationContext()new MyGeocoderTask(getApplicationContext()).execute(userLocale)
    • 这完全有效,非常感谢!!!但是你能解释一下它为什么起作用吗?我可能已经多次阅读context 的那些不同形式,但它们并没有真正沉入其中。:/
    • @NoniA。你需要玩current Context。就是这样。
    • 什么是当前上下文?我没听说过。
    【解决方案2】:

    似乎问题很可能是 Location.context 为空,因为 MD 建议并由错误链支持以

     at org.azurespot.practiceapp.location.MyGeocoderTask.doInBackground(MyGeocoderTask.java:26
    

    我认为是这里,对吧?

    Geocoder geocoder = new Geocoder(LocationMain.context);
    

    我没有在您的代码中看到您分配 LocationMain.context 的任何地方,但也许我错过了一些东西, 但我原以为你可以通过添加很容易解决这个问题

    Location.context = this.getApplicationContext():
    

    在 onResume() 或 onCreate() 中的某个位置。

    【讨论】:

    • 感谢您的解释,虽然 MD 确实先解决了它,所以我会以他作为答案,但我喜欢您的详细信息,它们确实增加了理解。 :)
    • 是的,我确实使用了LocationMain.context,希望它会选择LocationMaincontext,但我猜那不是正确的代码。感谢您指出。
    • 是的,您指的是您声明但从未分配的静态变量上下文。
    • 那么赋值意味着,在构造函数中声明它?
    • 您已经在以下行中声明了它:受保护的静态上下文上下文;但你从来没有给它赋值。在您调用任务之前,您需要为您在此处声明的变量“上下文”赋予一个值——当前应用程序上下文。您可以在 onCreate 或 onResume 等生命周期方法之一中执行此操作。否则它只是空的。您也可以在调用异步任务时传递它,但我只是按照您的代码执行方式,它调用静态类变量,如果它被分配了值,它也可以工作。跨度>
    猜你喜欢
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    • 2017-11-15
    • 2020-02-11
    • 2015-08-15
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多