简体   繁体   English

NullPointer异常将Intent字符串保存为Instance State Android

[英]NullPointer Exception Saving Intent string as Instance State Android

I´ve got a little saveInstanceState problem. 我有一点saveInstanceState问题。

One activity sends via intent a string value to another activity, which works fantastic. 一个活动通过意图将字符串值发送到另一个活动,这非常有效。 Now at the second activity I select one row item to get to a third activity, which works also. 现在在第二个活动中,我选择一个行项目来进行第三个活动,这也是有效的。 But if I use the actionbar BACK button (to the second activity) I get a NullPointerException. 但是如果我使用操作栏BACK按钮(到第二个活动),我会得到一个NullPointerException。

The reason is - of course - the intent string from the first activity can´t be loaded. 原因是 - 当然 - 无法加载第一个活动的意图字符串。 So at the second activity I tried saving this intent string value as instance state and get this value at oncreate methode again. 所以在第二个活动中,我尝试将此意图字符串值保存为实例状态,并再次在oncreate方法中获取此值。 I´ve googlet a lot, I´ve tried a lot. 我googlet很多,我尝试了很多。 But the Nullpointer won´t disappear. 但Nullpointer不会消失。

Would be great to have a little hint. 有一点提示会很高兴。

My Code of the second activity: 我的第二项活动代码:

    package de.cityknight.app;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class RouteChooseActivity extends ActionBarActivity implements OnItemClickListener {

    String citySave;
    String[] titelRoute;
    String[] descRoute;
    Integer[] bildRoute;

    ListView listView;
    List<RowItem> rowItems;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_route_choose);
        Bundle b = getIntent().getExtras();
        if (savedInstanceState != null) {
                savedInstanceState.getString("stadt");
         }
         else {
            b.getString("stadt");
         }
            TextView headingRoute = (TextView) findViewById(R.id.routeTitel);
            headingRoute.setText(String.format(getResources().getString(R.string.route_text)) + " " + b.getString("stadt") + " aus:");
            if (b.getString("stadt").equals("Passau")) {
                titelRoute = new String[]{"Die Altstadt", "Universität", "Essen und Trinken"};
                descRoute = new String[]{"Die Altstadt Passaus bietet viele Attraktion: Rathaus, Dom und die vielen kleinen Gassen.",
                        "Deutschlands schönster Campus.", "Kulinarische Köstlichkeiten in Passau"};
                bildRoute = new Integer[]{R.drawable.augsburg, R.drawable.bamberg, R.drawable.passau};
            } else if (b.getString("stadt").equals("Augsburg")) {
                titelRoute = new String[]{"Augsburg1", "Augsburg2", "Augsburg3"};
                descRoute = new String[]{"Bla bla", "Mehr Bla", "Blubb"};
                bildRoute = new Integer[]{R.drawable.augsburg, R.drawable.bamberg, R.drawable.passau};
            } else if (b.getString("stadt").equals("Bamberg")) {
                titelRoute = new String[]{"Bamberg", "Bamberg2", "Bamberg3"};
                descRoute = new String[]{"Bla bla", "Mehr Bla", "Blubb"};
                bildRoute = new Integer[]{R.drawable.augsburg, R.drawable.bamberg, R.drawable.passau};
            } else {
                try {
                    TextView errorMessage = (TextView) findViewById(R.id.routeTitel);
                    errorMessage.setText(R.string.errorroute);
                } catch (NullPointerException e) {
                    Context context = getApplicationContext();
                    CharSequence text = getResources().getString(R.string.errorroute);
                    int duration = Toast.LENGTH_LONG;
                    Toast toast = Toast.makeText(context, text, duration);
                    toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
                    toast.show();
                }

            }

            try {
                rowItems = new ArrayList<RowItem>();
                for (int i = 0; i < titelRoute.length; i++) {
                    RowItem item = new RowItem(bildRoute[i], titelRoute[i], descRoute[i]);
                    rowItems.add(item);
                }
                Comparator<RowItem> sortRoutes = new Comparator<RowItem>() {
                    @Override
                    public int compare(RowItem rowItem1, RowItem rowItem2) {
                        return rowItem1.getTitle().compareTo(rowItem2.getTitle());
                    }
                };
                Collections.sort(rowItems, sortRoutes);
                listView = (ListView) findViewById(R.id.listRoute);
                CityListViewAdapter adapter = new CityListViewAdapter(this, R.layout.row_items, rowItems);
                listView.setAdapter(adapter);
                listView.setOnItemClickListener(this);
            } catch (ArrayIndexOutOfBoundsException rowItems) {
                Context context = getApplicationContext();
                CharSequence text = getResources().getString(R.string.ressourcefailed);
                int duration = Toast.LENGTH_LONG;
                Toast toast = Toast.makeText(context, text, duration);
                toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
                toast.show();
            }

    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Intent intent = new Intent();
        intent.setClass(RouteChooseActivity.this, RouteView.class);
        RowItem item = (RowItem) parent.getItemAtPosition(position);
        Bundle b = new Bundle();
        b.putString("route", item.getTitle().toString());
        intent.putExtras(b);
        startActivity(intent);
    }

    protected void onSaveInstanceState(Bundle savedInstanceState) {
        Bundle b = getIntent().getExtras();
        b.getString("stadt");
        savedInstanceState.putString("stadt", citySave);
        super.onSaveInstanceState(savedInstanceState);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // Restore UI state from the savedInstanceState.
        // This bundle has also been passed to onCreate.
        savedInstanceState.getString(citySave);
        Log.i("debug", "saved data: " + citySave);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.route, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        switch (item.getItemId()) {
            case R.id.action_stadt:
                setContentView(R.layout.activity_stadt);
                Intent stadt = new Intent(RouteChooseActivity.this, StadtActivity.class);
                startActivity(stadt);
                return true;
            case R.id.action_help:
                setContentView(R.layout.activity_help);
                Intent help = new Intent(RouteChooseActivity.this, Help.class);
                startActivity(help);
                return true;
            case R.id.action_exit:
                moveTaskToBack(true);
                System.exit(0);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    }
  1. That will raise a NullPointerException : 这将引发NullPointerException:

     savedInstanceState.getString(citySave); Log.i("debug", "saved data: " + citySave); 

    It should be : 它应该是 :

     citySave = savedInstanceState.getString("stadt"); Log.i("debug", "saved data: " + citySave); 
  2. In onSaveInstanceState you should call super.onSaveInstanceState(savedInstanceState); onSaveInstanceState您应该调用super.onSaveInstanceState(savedInstanceState); before adding strings to savedInstanceState (or it will be wiped out ...) 在将字符串添加到savedInstanceState之前(或者它将被删除...)

  3. The whole savedInstanceState is not really suited for that purpose. 整个savedInstanceState并不适合这个目的。 Android can delete it when you go to your 3th activity ! 当您进入第3个活动时,Android 可以将其删除! (it depends if the system thinks that it needs memory and thus completly destroys the 2th activity and its savedInstanceState with it). (这取决于系统是否认为它需要内存,因此完全破坏第2个活动及其savedInstanceState)。

    The good way of doing things is to override the onBackPressed() method of your 3th activity to fire an intent to launch your 2th activity with the value put in the "Extra" bundle of the Intent. 做事的好方法是覆盖第3个活动的onBackPressed()方法,以使用Intent的“Extra”包中的值放置启动第2个活动的意图。

    With this approach your issue should be resolved. 使用这种方法,您的问题应该得到解决。

You have two errors as I can see: 我可以看到你有两个错误:

Firstly, you haven't actually used the savedInstanceState. 首先,您实际上没有使用savedInstanceState。 Yes you are calling the function, but nowhere are you actually using the value it returns. 是的,你正在调用该函数,但实际上你没有使用它返回的值。

String myNewString;
Bundle b = getIntent().getExtras();
if (savedInstanceState != null) {
    myNewString = savedInstanceState.getString("stadt");
} else {
    myNewString = b.getString("stadt");
}

Now use myNewString instead of b.getString("stadt") . 现在使用myNewString而不是b.getString("stadt")

Secondly,try putting the code into the onResume function. 其次,尝试将代码放入onResume函数中。 the onCreate() function will not run if you are pressing the back button to return to the second activity. 如果按后退按钮返回第二个活动,onCreate()函数将不会运行。

I´ve figured it out. 我弄清楚了。

You need three things for getting a good lifecycle - savedInstanceState if your activity is destroyed, - onResume, if your activity is paused by another app or activity screen, for example if you select a rowItem, which starts a new activity. 如果您的活动被销毁,则需要三件事来获得良好的生命周期 - savedInstanceState - 如果您的活动被其他应用或活动屏幕暂停,则为onResume,例如,如果您选择rowItem,则会启动新活动。

For my problem the following did it: Second activity: 对于我的问题,以下是这样做的:第二项活动:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_route_choose);
        Bundle b = getIntent().getExtras();
        citySave = b.getString("stadt");

@Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Intent intent = new Intent();
        intent.setClass(RouteChooseActivity.this, RouteView.class);
        RowItem item = (RowItem) parent.getItemAtPosition(position);
        Bundle b = new Bundle();
        b.putString("route", item.getTitle().toString());
        b.putString("stadt", citySave);
        intent.putExtras(b);
        startActivity(intent);
    }

    protected void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        Bundle b = getIntent().getExtras();
        citySave = b.getString("stadt");
        savedInstanceState.putString("stadt", citySave);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // Restore UI state from the savedInstanceState.
        // This bundle has also been passed to onCreate.
        citySave = savedInstanceState.getString("stadt");
        Log.i("debug", "saved data: " + citySave);
    }

    public void onResume() {
        super.onResume();

            Bundle b = getIntent().getExtras();
            citySave = b.getString("stadt");

    }

Third activity: 第三项活动:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_route_view);
        Bundle b = getIntent().getExtras();
        b.getString("route");
        citySave = b.getString("stadt");

    public void onBackPressed() {
        super.onBackPressed();
        Intent intent = new Intent();
        intent.setClass(RouteView.this, RouteChooseActivity.class);
        Bundle b = new Bundle();
        b.putString("stadt", citySave);
        intent.putExtras(b);
        startActivity(intent);
        finish();
    }

    public void onPause() {
        super.onPause();
        Intent intent = new Intent();
        intent.setClass(RouteView.this, RouteChooseActivity.class);
        Bundle b = new Bundle();
        b.putString("stadt", citySave);
        intent.putExtras(b);
        startActivity(intent);
        finish();
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM