0

我目前正在尝试调试我的应用程序,但是,我遇到了 NullPointerException 的一些困难。我有一个带有 4 个复选框、一个保存按钮和一个取消按钮的对话框。当用户在对话框中标记他们的选择然后按下保存按钮时,它返回 NullPointerException,我不明白为什么。以下是与查找解决方案相关的 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollviewPref"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:layout_marginTop="10dip">

    <LinearLayout
        android:layout_width="300dip"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:minWidth="200dip">

            <CheckBox
                android:id="@+id/altitudeCheckbox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Altitude"
                android:layout_gravity="left" />

            <CheckBox
                android:id="@+id/latitudeCheckbox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Latitude"
                android:layout_gravity="left" />

            <CheckBox
                android:id="@+id/longitudeCheckbox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Longitude"
                android:layout_gravity="left" />

            <CheckBox
                android:id="@+id/velocityCheckbox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Velocity"
                android:layout_gravity="left" />

            <LinearLayout 
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dip"
                android:layout_marginRight="10dip"
                android:layout_marginBottom="10dip"
                android:layout_marginTop="10dip">

                    <Button
                        android:id="@+id/saveBtn"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:text="Save"
                        android:layout_weight="1" />

                    <Button
                        android:id="@+id/cancelBtn"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:text="Cancel"
                        android:layout_weight="1" />

    </LinearLayout>

</LinearLayout>

</ScrollView>

代码集是将用户的选择保存到 SharedPreferences 的代码。

package shc_BalloonSat.namespace;
import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;

public class CheckPreferences extends Dialog
{
Context shc;
private CheckBox altitudeCheckBox = null;
private CheckBox latitudeCheckbox = null;
private CheckBox longitudeCheckbox = null;
private CheckBox velocityCheckbox = null;
private CheckPreferencesListener listener;
SharedPreferences pref;
Editor prefEditor;
String userAltitudePreference = "";
String userLatitudePreference = "";
String userLongitudePreference = "";
String userVelocityPreference = "";
String userAltitudeChoice = "";
String userLatitudeChoice = "";
String userLongitudeChoice = "";
String userVelocityChoice = "";

public interface CheckPreferencesListener 
{
public void onSettingsSaved();
public void onCancel();
}

public CheckPreferences(Context context, CheckPreferencesListener l)
{
super(context);
shc = context;
this.listener = l;
this.setContentView(R.layout.custompreferences);

altitudeCheckBox = (CheckBox) findViewById(R.id.altitudeCheckbox);
latitudeCheckbox = (CheckBox) findViewById(R.id.latitudeCheckbox);
longitudeCheckbox = (CheckBox) findViewById(R.id.longitudeCheckbox);
velocityCheckbox = (CheckBox) findViewById(R.id.velocityCheckbox);

this.setCancelable(false);
this.setCanceledOnTouchOutside(false);
this.setTitle("Data View Settings");
pref = shc.getSharedPreferences("shared_prefs", 1);
prefEditor = pref.edit();
initOnClick();
}

private void initOnClick()
{
View.OnClickListener click = new View.OnClickListener()
{
    public void onClick(View v)
    {
    switch (v.getId())
    {
            case R.id.saveBtn:
            {
                saveSettings();
                listener.onSettingsSaved();
                dismiss();
                break;
            }

            case R.id.cancelBtn:
            {
                listener.onCancel();
                dismiss();
                break;
            }
    }
    }
};

    // Save Button
    this.findViewById(R.id.saveBtn).setOnClickListener(click);

    // Cancel Button
    this.findViewById(R.id.cancelBtn).setOnClickListener(click);
}

// This function is called when the user chooses the save their preferences
public void saveSettings()
{
try
{
    if (altitudeCheckBox.isChecked())
    {
    userAltitudeChoice = "true";
    prefEditor.putString(userAltitudePreference, userAltitudeChoice);
    prefEditor.commit();
    }
    else if (latitudeCheckbox.isChecked())
    {
    userLatitudeChoice = "true";
    prefEditor.putString(userLatitudePreference, userLatitudeChoice);
    prefEditor.commit();
    }

    else if (longitudeCheckbox.isChecked())
    {
    userLongitudeChoice = "true";
    prefEditor.putString(userLongitudePreference, userLongitudeChoice);
        prefEditor.commit();  
    }

    else if (velocityCheckbox.isChecked())
    {
    userVelocityChoice = "true";
    prefEditor.putString(userVelocityPreference, userVelocityChoice);
    prefEditor.commit(); 
    }

    else
    {

    } 
}

catch (NullPointerException npe)
{
    if (npe.getMessage() != null)
    {
            Log.e("<tag>", npe.getMessage());
    }

    else
    {
    Log.e("<tag>", "Save Settings e.getMessage() was null");
    }
}
}
}

NullPointerException 发生在 savedSettings 函数中。该函数所做的只是将数据放入 SharedPreferences 中。知道为什么这会导致某些东西为空吗?提前感谢您提供的任何帮助。

更新:以下是错误日志。

05-09 17:25:28.835: E/<tag>(5447): Save Settings e.getMessage() was null
05-09 17:25:28.866: E/AndroidRuntime(5447): FATAL EXCEPTION: main
05-09 17:25:28.866: E/AndroidRuntime(5447): java.lang.NullPointerException
05-09 17:25:28.866: E/AndroidRuntime(5447):     at shc_BalloonSat.namespace.CheckPreferences$1.onClick(CheckPreferences.java:59)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at android.view.View.performClick(View.java:2408)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at android.view.View$PerformClick.run(View.java:8816)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at android.os.Handler.handleCallback(Handler.java:587)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at android.os.Handler.dispatchMessage(Handler.java:92)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at android.os.Looper.loop(Looper.java:123)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at android.app.ActivityThread.main(ActivityThread.java:4627)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at java.lang.reflect.Method.invokeNative(Native Method)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at java.lang.reflect.Method.invoke(Method.java:521)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
05-09 17:25:28.866: E/AndroidRuntime(5447):     at dalvik.system.NativeStart.main(Native Method)

下面是我在其中实例化侦听器的主类。

package shc_BalloonSat.namespace;
import java.text.DecimalFormat;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.TextView;
import android.widget.Toast;

public class Shc_BalloonSat_Activity extends Activity
{
int historyCountFromUser;
httpAPI api;
mapAPI map;
runDialog dialog;
CheckPreferences check;
DecimalFormat df = new DecimalFormat("##.#####");
DecimalFormat decimalf = new DecimalFormat("##.######");
AlertDialog alert;
SharedPreferences pref;
Editor prefEditor;
String lastpacketsPHP;
TextView historyTV;
TextView infoTV;

// User to determine how many packet the user would like to see.
int userDefinedCount = 5;

/*
 *  Called when the activity is first created. 
*/

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    loadApp();
}

public boolean isNetworkConnected(Context context)
{
    ConnectivityManager connectionManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectionManager.getActiveNetworkInfo() != null && connectionManager.getActiveNetworkInfo().isAvailable() && connectionManager.getActiveNetworkInfo().isConnected())
    {
        return true;
    }

    else 
    {
        return false;
    }
}

public void showAlert()
{
    alert.setTitle("Sorry!");
    alert.setMessage("Please connect to the internet to access the full functionality of this app.");
    alert.setButton("OK", new DialogInterface.OnClickListener()
    {
        public void onClick(DialogInterface dialog, int which)
        {

        }
    });
    alert.show();
}

public void loadApp()
{
    setContentView(shc_BalloonSat.namespace.R.layout.main);
    alert = new AlertDialog.Builder(this).create();
    lastpacketsPHP = "";
    pref = getSharedPreferences("shared_prefs", 1);
    prefEditor = pref.edit();
    //prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
    //prefEditor.commit();

    // These next two lines are used to test the PHP files on the SHC server by determining if PHP is set up correctly.
    prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
    prefEditor.commit();   

    if (!isNetworkConnected(this))
    {
    showAlert();
    }

    else
    {
    api = new httpAPI(this);
        map = new mapAPI(this);
        dialog = new runDialog(this, api, new runDialog.OnDataLoadedListener()
        {

            public void dataLoaded(String textViewString)
            {
            infoTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.info);
                infoTV.setText(textViewString);
            }
        });

        dialog.execute();
    }

    CheckPreferences cp = new CheckPreferences(this, new CheckPreferences.CheckPreferencesListener()
    {

        public void onSettingsSaved()
        {
            // This function let's the activity know that the user has saved their preferences and
            // that the rest of the app should be now be shown.
            check.saveSettings();
            assignInfoToInfoTextView();
            assignInfoToHistoryTextView();
        }

        public void onCancel()
        {
            Toast.makeText(getApplicationContext(), "Settings dialog cancelled", Toast.LENGTH_LONG).show();
        }
    });

    cp.show();
}

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(shc_BalloonSat.namespace.R.menu.mainmenu, menu);

    SubMenu submenu = menu.addSubMenu(0, Menu.FIRST, Menu.NONE, "Preferences");
    submenu.add(0, 5, Menu.NONE, "Get Last 5 Packets");
    submenu.add(0, 10, Menu.NONE, "Get Last 10 Packets");
    submenu.add(0, 20, Menu.NONE, "Get Last 20 Packets");
    inflater.inflate(shc_BalloonSat.namespace.R.menu.mainmenu, submenu);

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    // Handle item selection
    switch (item.getItemId())
    {
        case shc_BalloonSat.namespace.R.id.viewKML:
            viewKML();
            return true;
        case 5:
            viewLast5Packets();
            return true;
        case 10:
            viewLast10Packets();
            return true;
        case 20:
            viewLast20Packets();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

public void assignInfoToInfoTextView()
{       
    try
    {
        String result = api.result.substring(1, api.result.length()-2);
        JSONObject json_data = new JSONObject(result);
        String infoText = "";

        if (check.userAltitudePreference.equals("true"))
        {
        double altitudeData = json_data.getDouble("altitude");
        double altitudeInFeet = altitudeData * 3.281;
        infoText = "Last Known Altitude: " + df.format(altitudeInFeet) + " ft\n";
        }

        else if (check.userVelocityPreference.equals("true"))
        {
        Double speedData = json_data.optDouble("speed");

        if (speedData.isNaN())
        {
            speedData = 0.00;
        }

        Double direction = json_data.optDouble("heading");
        String directionUnits = " degrees from N";
        String directionText = "";

        if (direction == 0)
        {
            directionText = ", N";
        }

        else if (direction > 0 && direction < 45)
        {
            directionText = ", N NE";
        }

        else if (direction == 45)
        {
            directionText = ", NE";
        }

        else if (direction > 45 && direction < 90)
        {
            directionText = ", E NE";
        }

        else if (direction == 90)
        {
            directionText = ", E";
        }

        else if (direction > 90 && direction < 135)
        {
            directionText = ", E SE";
        }

        else if (direction == 135)
        {
            directionText = ", SE";
        }

        else if (direction > 135 && direction < 180)
        {
            directionText = ", S SE";
        }

        else if (direction == 180)
        {
            directionText = ", S";
        }

        else if (direction > 180 && direction < 225)
        {
            directionText = ", S SW";
        }

        else if (direction == 225)
        {
            directionText = ", SW";
        }

        else if (direction > 225 && direction < 270)
        {
            directionText = ", W SW";
        }

        else if (direction == 270)
        {
            directionText = ", W";
        }

        else if (direction > 270 && direction < 315)
        {
            directionText = ", W NW";
        }

        else if (direction == 315)
        {
            directionText = ", NW";
        }

        else if (direction > 315 && direction < 360)
        {
            directionText = ", N NW";
        }

        else if (direction.isNaN())
            {
            directionText = " Invalid direction";
            }

        else
        {

            }

        infoText += "Last Known Velocity: " + df.format(speedData) + " m/s " + direction + directionUnits + directionText + "\n";
        }

        else if (check.userLatitudePreference.equals("true"))
        {
        double recentLatitudeData = json_data.getDouble("latitude");
        infoText += "Last Known Latitude: " + df.format(recentLatitudeData) + "\n";
        }

        else if (check.userLongitudePreference.equals("true"))
        {
        double recentLongitudeData = json_data.getDouble("longitude");
        infoText += "Last Known Longtitude: " + df.format(recentLongitudeData) + "\n";
        }

        infoTV.setText(infoText);
    }

    catch (JSONException e)
    {
        if (e.getMessage() != null)
        {
        Log.e("<tag>", e.getMessage());
        }

        else
        {
        Log.e("<tag>", "Last Known Textview 1 e.getMessage() was null");
        }

        Toast.makeText(this,"JSON Error in (Last Known) method!",Toast.LENGTH_SHORT).show();

    }

    catch (Exception e)
    {
        //broke here, not getting a message for some reason
    if (e.getMessage() != null)
    {
            Log.e("<tag>", e.getMessage());
    }

    else
    {
    Log.e("<tag>", "Last Known Textview 2 e.getMessage() was null");
    }

    Toast.makeText(this,"Error in (Last Known) method!",Toast.LENGTH_SHORT).show();
    }
}

public void assignInfoToHistoryTextView()
{

    try
    {
        JSONArray jArray = new JSONArray(api.result);
        historyTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.history);

        for (int count = 1; count < userDefinedCount; count++)
        {
                JSONObject json_data = jArray.getJSONObject(count);

                double altitudeData = json_data.getDouble("altitude");
                double altitudeInFeet = altitudeData * 3.281;
                String historyText = "Altitude: " + decimalf.format(altitudeInFeet) + " ft\n";

                Double speedData = json_data.optDouble("speed");

                if (speedData.isNaN())
                {
                    speedData = 0.00;
                }

                    Double direction = json_data.optDouble("heading");
                    String directionUnits = " degrees from N";
            String directionText = "";

            if (direction == 0)
            {
                directionText = ", N";
            }
            else if (direction > 0 && direction < 45)
            {
                directionText = ", N NE";
            }

            else if (direction == 45)
            {
                directionText = ", NE";
            }

            else if (direction > 45 && direction < 90)
            {
                directionText = ", E NE";
            }

            else if (direction == 90)
            {
                directionText = ", E";
            }

            else if (direction > 90 && direction < 135)
            {
                directionText = ", E SE";
            }

            else if (direction == 135)
            {
                directionText = ", SE";
            }

            else if (direction > 135 && direction < 180)
            {
                directionText = ", S SE";
            }

            else if (direction == 180)
            {
                directionText = ", S";
            }

            else if (direction > 180 && direction < 225)
            {
                directionText = ", S SW";
            }

            else if (direction == 225)
            {
                directionText = ", SW";
            }

            else if (direction > 225 && direction < 270)
            {
                directionText = ", W SW";
            }

            else if (direction == 270)
            {
                directionText = ", W";
            }

            else if (direction > 270 && direction < 315)
            {
                directionText = ", W NW";
            }

            else if (direction == 315)
            {
                directionText = ", NW";
            }

            else if (direction > 315 && direction < 360)
            {
                directionText = ", N NW";
            }

            else if (direction.isNaN())
            {
                directionText = " Invalid direction";
            }

            else
            {

            }

            if (direction.isNaN())
            {
                historyText += "Velocity: " + df.format(speedData) + " m/s " + directionText + "\n";
            }

            else
            {
                historyText += "Velocity: " + df.format(speedData) + " m/s,\n" + direction + directionUnits + directionText + "\n";
            }

                double latitudeData = json_data.getDouble("latitude");
                historyText += "Latitude: " + df.format(latitudeData) + "\n";

                double longitudeData = json_data.getDouble("longitude");
                historyText += "Longtitude: " + df.format(longitudeData) + "\n\n";

                historyTV.setText(historyTV.getText().toString() + historyText);
        }
    }

    catch (JSONException e)
    {
        if (e.getMessage() != null)
        {
        Log.e("log_tag", "Error parsing data: " + e.toString());
        }

        else
    {
    Log.e("<tag>", "History TextView 1 e.getMessage() was null");
    }   
    }

    catch(Exception e)
    {
        if (e.getMessage() != null)
    {
        Log.e("log_tag", "Error parsing data: " + e.toString());
    }

        else
    {
    Log.e("<tag>", "History TextView 2 e.getMessage() was null");
    }

    }

}

void viewLast5Packets()
{
    if (!isNetworkConnected(this))
    {
        showAlert();
    }

    else
    {
        historyTV.setText("");

        userDefinedCount = 5;
        //prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
        //prefEditor.commit();

        // These next two lines are used to test the PHP files on the SHC server by determining if PHP is set up correctly.
        prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
        prefEditor.commit();

        dialog = new runDialog(this, api, new runDialog.OnDataLoadedListener()
        {
        public void dataLoaded(String textViewString)
        {
            TextView infoTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.info);
            infoTV.setText(textViewString);
            assignInfoToInfoTextView();
            assignInfoToHistoryTextView();
        }
        });

        dialog.execute();
    }
}

void viewLast10Packets()
{
    if (!isNetworkConnected(this))
    {
        showAlert();
    }

    else
    {
        historyTV.setText("");           

    userDefinedCount = 10;
    //prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
    //prefEditor.commit();

    // These next two lines are used to test the PHP files on the SHC server by determining if PHP is set up correctly.
    prefEditor.putString(lastpacketsPHP, \* PHP file location goes here. */");
    prefEditor.commit();

    dialog = new runDialog(this, api, new runDialog.OnDataLoadedListener()
    {
    public void dataLoaded(String textViewString)
    {
        TextView infoTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.info);
        infoTV.setText(textViewString);
        assignInfoToInfoTextView();
        assignInfoToHistoryTextView();
    }
    });

    dialog.execute();
    }
}

void viewLast20Packets()
{
    if (!isNetworkConnected(this))
    {
        showAlert();
    }

    else
    {
            historyTV.setText("");
        userDefinedCount = 20;
        //prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
        //prefEditor.commit();

        // These next two lines are used to test the PHP files on the SHC server by determining if PHP is set up correctly.
    prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
    prefEditor.commit();

        dialog = new runDialog(this, api, new runDialog.OnDataLoadedListener()
        {

            public void dataLoaded(String textViewString)
            {
            TextView infoTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.info);
                infoTV.setText(textViewString);
                assignInfoToInfoTextView();
                assignInfoToHistoryTextView();
            }
        });

        dialog.execute();
    }
}

public void viewKML()
{
    if (!isNetworkConnected(this))
    {
        showAlert();
    }

    else
    {
        map.openKML();
    }
}
}
4

3 回答 3

0

最容易找到 NullPointerException 原因的方法是查看调试 logcat 输出。它将准确地向您显示问题发生的位置。

只需查找以您的包名称开头的第一行,就可以了。

ps你需要从你的代码中取出catch,这样代码就会崩溃

或者如果找不到,请发布日志。

于 2012-05-09T22:14:24.270 回答
0

从对代码的粗略检查来看,您似乎从未初始化过listener,所以当您这样做时listener.onSettingsSaved();它会崩溃。

编辑:

伙计,你仍然永远不会设置它:

public CheckPreferences(Context context, CheckPreferencesListener l)
{
super(context);
shc = context;
this.setContentView(R.layout.custompreferences);
this.setCancelable(false);
this.setCanceledOnTouchOutside(false);
this.setTitle("Data View Settings");
pref = shc.getSharedPreferences("shared_prefs", 1);
prefEditor = pref.edit();
initOnClick();
}

你失踪了this.listener = l;

于 2012-05-09T22:15:50.527 回答
0

我的想法是

private CheckBox altitudeCheckBox = (CheckBox) findViewById(R.id.altitudeCheckbox);
private CheckBox latitudeCheckbox = (CheckBox) findViewById(R.id.latitudeCheckbox);
private CheckBox longitudeCheckbox = (CheckBox) findViewById(R.id.longitudeCheckbox);
private CheckBox velocityCheckbox = (CheckBox) findViewById(R.id.velocityCheckbox);

在对话框的构造函数之前调用,因此它们为空,因为 findViewById 找不到布局视图。尝试将它们更改为:

private CheckBox altitudeCheckBox = null;
private CheckBox latitudeCheckbox = null;
private CheckBox longitudeCheckbox = null;
private CheckBox velocityCheckbox = null;

然后在构造函数中的 this.setContentView(R.layout.custompreferences) 行之后添加以下内容:

altitudeCheckBox = (CheckBox) findViewById(R.id.altitudeCheckbox);
latitudeCheckbox = (CheckBox) findViewById(R.id.latitudeCheckbox);
longitudeCheckbox = (CheckBox) findViewById(R.id.longitudeCheckbox);
velocityCheckbox = (CheckBox) findViewById(R.id.velocityCheckbox);

希望这可以帮助...

于 2012-05-09T22:37:26.420 回答