2017-02-19 100 views
-4

我使用gson在SharedPreferences中保存了一個對象(Account),但是在訪問新Activity中的對象後,對象實例(newAccount)導致我使用newAccount.returnName()給出NullPointerException。錯誤是:引起:java.lang.NullPointerException:試圖在空對象引用上調用虛擬方法'java.lang.String com.cashtrack.kennethlee.cashtrack.Account.returnName()'。我明白什麼是NullPointer錯誤,但我不明白爲什麼我可能會得到它,因爲我是Android Studio的新手。第一個活動的代碼是:爲什麼在從SharedPreferences訪問對象後得到一個NullPointerException?

package com.cashtrack.kennethlee.cashtrack; 

import android.content.Context; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.support.v4.view.MenuItemCompat; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.widget.EditText; 
import android.widget.TextView; 

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.ArrayList; 

public class CreateAccount extends AppCompatActivity { 

    SharedPreferences accountsPref; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_create_account); 
     setTitle("Create New Account"); 
     getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
     accountsPref = getPreferences(MODE_PRIVATE); 
    } 

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

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      //back button 
      case android.R.id.home: 
       // app icon in action bar clicked; go home 
       Intent intent = new Intent(this, MainScreen.class); 
       intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
       startActivity(intent); 
       return true; 

      //save button 
      case R.id.action_menu_save: 

       // get EditText by id 
       EditText inputTxt1 = (EditText) findViewById(R.id.AccountName); 
       // Store EditText in Variable 
       String name = inputTxt1.getText().toString(); 

       EditText inputTxt2 = (EditText) findViewById(R.id.StartingBalance); 
       double balance = Double.parseDouble(inputTxt2.getText().toString()); 

       Account newAccount = new Account(name, balance); 

       SharedPreferences.Editor editor = accountsPref.edit(); 
       Gson gson = new Gson(); 
       String json = gson.toJson(newAccount); 
       editor.putString("newAccount", json); 
       editor.commit(); 

       Intent intent2 = new Intent(this, MainScreen.class); 
       intent2.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
       startActivity(intent2); 
       return true; 
      default: 
       return super.onOptionsItemSelected(item); 
     } 
    } 
} 

用於訪問該對象,並導致錯誤的行爲的代碼是:

package com.cashtrack.kennethlee.cashtrack; 

import android.content.Context; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.os.Bundle; 
import android.support.design.widget.FloatingActionButton; 
import android.support.design.widget.Snackbar; 
import android.support.v7.app.AppCompatActivity; 
import android.support.v7.widget.Toolbar; 
import android.view.View; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.widget.TextView; 

import com.google.gson.Gson; 

import java.io.FileInputStream; 
import java.io.StringWriter; 
import java.util.ArrayList; 

public class MainScreen extends AppCompatActivity { 
    //array list of accounts 
    ArrayList<Account> accounts = new ArrayList<>(); 

    SharedPreferences accountsPref; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main_screen); 
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 

     FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
     fab.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       startActivity(new Intent(MainScreen.this, CreateAccount.class)); 
      } 
     }); 
     accountsPref = getPreferences(MODE_PRIVATE); 

     // PRINT TO A TEXT BOX 
     //setContentView(R.layout.activity_main_screen); 
     //TextView textView = (TextView) findViewById(R.id.textView4); 
     //textView.setText(hello.returnName()); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.menu_main_screen, 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. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 

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

     Gson gson = new Gson(); 
     String json = accountsPref.getString("newAccount", ""); 
     Account newAccount = gson.fromJson(json, Account.class); 
     accounts.add(newAccount); 


     setContentView(R.layout.activity_main_screen); 
     TextView textView1 = (TextView) findViewById(R.id.textView5); 
     textView1.setText(accounts.get(0).returnName()); 

     TextView textView2 = (TextView) findViewById(R.id.textView6); 
     textView2.setText(Double.toString(accounts.get(0).returnAvailableBalance())); 
    } 
} 

回答

0

您正在使用MODE_PRIVATE來指定存儲該值的文件名。推薦的方法是使用默認模式,而不指定文件名。就像這樣:

認沽值:

accountPref = PreferenceManager.getDefaultSharedPreferences(this); 
Gson gson = new Gson(); 
String json = gson.toJson(Account); 
accountPref.edit().putString("newAccount", json).apply(); 

獲得價值:

SharedPreferences accountsPref = PreferenceManager.getDefaultSharedPreferences(this); 
if (accountsPref.contains("newAccount")) { 
    Gson gson = new Gson(); 
    String json = accountsPref.getString("newAccount", ""); 
    Account newAccount = gson.fromJson(json, Account.class); 
    accounts.add(newAccount); 
} 

希望你喜歡這個。 :)

+0

獲取字符串json(獲取值的第三行)後,如何獲取對象本身? –

+0

哪個對象?你沒有得到你在CreateAccount活動中放置的字符串值嗎?你想要從該特定的SharedPreference中提出新的價值或去除價值嗎? – tahsinRupam

+0

我希望能夠使用CreateAccount中名爲newAccount的類Account的實例。我在MainScreen中有一個帳戶ArrayList,我想從CreateAccount添加新帳戶到該ArrayList中。 –

0

我想你一定在的onCreate初始化您的賬戶類() 。

沒有初始化,它導致空指針異常。

在賬戶類中你已經創建了帶有Context參數的構造函數?

+0

我在案例中初始化了,因爲我得到了那裏的對象的名稱和平衡變量,所以我必須在得到兩個變量後進行初始化。我也沒有在帳戶類構造函數中的上下文參數。那是什麼目的? –

0

我認爲你是有原因

getPreferences(int mode) 

回報SharedPreferences對象爲當前活動這個問題,因此字符串「newAccount」保存在的createAccount活動沒有在MainScreen活動檢索。

所以當您使用Account newAccount = gson.fromJson(json, Account.class); newAccount爲空時,因爲json是一個空字符串。

在您的活動中調用方法時,您可以考慮使用getSharedPreferences(String sharedPreferenceName, int mode)而不是getPreferences(int mode),使用相同的sharedPreferenceName

對不起,我的英語。 我希望這是幫助。

相關問題