1

我正在使用一个listview,点击打开一个对话框,其中包含一个edittext和一个按钮。点击按钮后,在editText中输入的值将保存在之前按下的listview项目的textView中。问题是如果我重新打开应用程序,价值不再保存。我试图使用sharedPrefences来保存它,但它崩溃并显示nullpointerexception并且无法处理它。因custon ListView中的NullPointerException导致应用程序崩溃

NoteAdapter.java:

package com.cngcnasaud.orar; 

    import java.util.Arrays; 

    import android.app.Dialog; 
    import android.content.Context; 
    import android.util.Log; 
    import android.view.LayoutInflater; 
    import android.view.View; 
    import android.view.View.OnClickListener; 
    import android.view.ViewGroup; 
    import android.widget.BaseAdapter; 
    import android.widget.Button; 
    import android.widget.EditText; 
    import android.widget.ImageView; 
    import android.widget.TextView; 

    public class NoteAdapter extends BaseAdapter { 

     String[] result; 
     Context context; 
     int[] imageId; 
     private static LayoutInflater inflater = null; 
     private Dialog dialog; 
     String[] savedEntries; 
     String[] saved = null; 

     public NoteAdapter(Note note, String[] saved, String[] prgmNameList) { 
      // TODO Auto-generated constructor stub 
      result = prgmNameList; 
      context = note; 
      inflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

      if (saved == null) { 
       savedEntries = new String[result.length]; 
       Arrays.fill(savedEntries, ""); 
      } else 
       savedEntries = saved; 

     } 

     @Override 
     public int getCount() { 
      // TODO Auto-generated method stub 
      return result.length; 
     } 

     @Override 
     public Object getItem(int position) { 
      // TODO Auto-generated method stub 
      return savedEntries[position]; 
     } 

     @Override 
     public long getItemId(int position) { 
      // TODO Auto-generated method stub 
      return position; 
     } 

     public class Holder { 
      TextView tv; 
      ImageView img; 
      public TextView text; 
     } 

     @Override 
     public View getView(final int position, View convertView, ViewGroup parent) { 
      // TODO Auto-generated method stub 

      final Holder holder = new Holder(); 
      View rowView; 
      rowView = inflater.inflate(R.layout.note_items, null); 
      holder.tv = (TextView) rowView.findViewById(R.id.textView1); 
      holder.text = (TextView) rowView.findViewById(R.id.textView2); 
      holder.text.setText(savedEntries[position]); 
      holder.img = (ImageView) rowView.findViewById(R.id.imageView1); 

      rowView.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // TODO Auto-generated method stub 
        dialog = new Dialog(context); 
        dialog.setContentView(R.layout.dialog); 
        dialog.setTitle("Materie:" + result[position]); 

        final EditText txtMode = (EditText) dialog 
          .findViewById(R.id.dialog); 
        Button btnSave = (Button) dialog.findViewById(R.id.bsave); 

        btnSave.setOnClickListener(new OnClickListener() { 

         @Override 
         public void onClick(View v) { 

          String data = txtMode.getText().toString(); 
          holder.text.setText(data); 

          savedEntries[position] = data; 

          dialog.dismiss(); 
          Log.d("data", data); 
         } 
        }); 
        dialog.show(); 
       } 

      }); 
      return rowView; 
     } 

    } 

logcat的:

04-19 04:14:32.130: E/AndroidRuntime(947): FATAL EXCEPTION: main 
04-19 04:14:32.130: E/AndroidRuntime(947): Process: com.cngcnasaud.orar, PID: 947 
04-19 04:14:32.130: E/AndroidRuntime(947): java.lang.NullPointerException 
04-19 04:14:32.130: E/AndroidRuntime(947): at com.cngcnasaud.orar.NoteAdapter.getView(NoteAdapter.java:76) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.AbsListView.obtainView(AbsListView.java:2263) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.ListView.makeAndAddView(ListView.java:1790) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.ListView.fillDown(ListView.java:691) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.ListView.fillFromTop(ListView.java:752) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.ListView.layoutChildren(ListView.java:1630) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.AbsListView.onLayout(AbsListView.java:2091) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at com.android.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:374) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.View.layout(View.java:14817) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewGroup.layout(ViewGroup.java:4631) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1987) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1744) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.Choreographer.doCallbacks(Choreographer.java:574) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.Choreographer.doFrame(Choreographer.java:544) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.os.Handler.handleCallback(Handler.java:733) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.os.Handler.dispatchMessage(Handler.java:95) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.os.Looper.loop(Looper.java:136) 
04-19 04:14:32.130: E/AndroidRuntime(947): at android.app.ActivityThread.main(ActivityThread.java:5017) 
04-19 04:14:32.130: E/AndroidRuntime(947): at java.lang.reflect.Method.invokeNative(Native Method) 
04-19 04:14:32.130: E/AndroidRuntime(947): at java.lang.reflect.Method.invoke(Method.java:515) 
04-19 04:14:32.130: E/AndroidRuntime(947): at com.android.internal.os. 

76行中NoteAdapter.java:

holder.text.setText(savedEntries[position]); 

适配器的构造 - Note.java:

package com.cngcnasaud.orar; 

import java.util.ArrayList; 

import android.os.Bundle; 
import android.app.Activity; 
import android.content.Context; 
import android.content.SharedPreferences; 
import android.view.Menu; 

import android.widget.ListAdapter; 
import android.widget.ListView; 
import android.widget.TextView; 

public class Note extends Activity { 

    public static final ListAdapter NoteAdapter = null; 
    ListView lv; 
    Context context; 
    ArrayList<?> prgmName; 
    TextView text; 

    public static String[] prgmNameList = { "Romana - ", "Matematica - ", 
      "Lb. Engleza - ", "Lb. Germana/Franceza - ", "Istorie - ", 
      "Geografie - ", "Biologie - ", "Fizica - ", "Ed. Fizica - " }; 

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

     text = (TextView) findViewById(R.id.textView2); 

     context = this; 

     lv = (ListView) findViewById(R.id.listView); 
     lv.setAdapter(new NoteAdapter(this, prgmNameList, null)); 

    } 

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

    @Override 
    protected void onStop() { 
     // TODO Auto-generated method stub 

     NoteAdapter adapter = (NoteAdapter) lv.getAdapter(); 

     // Variable is public for clarity. 
     String toSave = EncodeDecode.encode(adapter.savedEntries); 
     SharedPreferences.Editor editor = getSharedPreferences("LV Data", 
       MODE_PRIVATE).edit(); 
     editor.putString("TVEntries", toSave); 
     editor.commit(); 
    } 

    @Override 
    protected void onResume() { 
     // TODO Auto-generated method stub 

     SharedPreferences prefs = getSharedPreferences("LV Data", MODE_PRIVATE); 
     String encoded = prefs.getString("TVEntries", ""); 

     String[] entries; 
     if (encoded.equals("")) 
      entries = null; 
     else 
      entries = EncodeDecode.decode(encoded); 

     NoteAdapter adapter = (NoteAdapter) lv.getAdapter(); 
     adapter.savedEntries = entries; 
     lv.setAdapter(adapter); 

     super.onResume(); 
    } 

} 

EncodeDecode.java:

package com.cngcnasaud.orar; 

import java.util.ArrayList; 
import java.util.Arrays; 
import java.lang.StringBuffer; 

public class EncodeDecode 
{ 

    public static void main(String[] args) 
    { 
    //Test functionality. 
    String[] toEncode = {"a?b","c,d,", "asdas,dasd?,,,,,", "asdsad*\t  "}; 
    String encodedString = encode(toEncode); 
    String[] decodedArray = decode(encodedString); 
    System.out.println("Original Array: " + Arrays.toString(toEncode)); 
    System.out.println("Encoded String: " + encodedString); 
    System.out.println("Decoded Array: " + Arrays.toString(decodedArray)); 
    System.out.println(); 
    System.out.println("Testing equality of the arrays....."); 
    if(encode(toEncode).equals(encode(decodedArray))) 
     System.out.println("Passed!"); 
    else 
     System.out.println("Failed :(!"); 
    } 

    /** 
    * Function: encode 
    * -------------------- 
    * Encode a String array into a single String. 
    * 
    * toEncode: the String array to be encoded. 
    * 
    * returns: the encoded string. 
    */ 
    public static String encode(String[] toEncode) 
    { 
    StringBuffer strBuf = new StringBuffer(); 
    for(int i = 0; i < toEncode.length; i++) 
    { 
     /*Retrieve a representation of the current string element that is 
     easier to modify.*/ 
     StringBuffer curString = new StringBuffer(toEncode[i]); 
     for(int j = 0; j < curString.length(); j++) 
     //If we see a "break" character, prepend another "break" character to it. 
     if(curString.charAt(j) == '?') 
     { 
      curString.insert(j, '?'); 
      j++; 
     } 
     //If we see a delimiter character, prepend "break" character to it. 
     else if(curString.charAt(j) == ',') 
     { 
      curString.insert(j, '?'); 
      j++; 
     } 

     //Add the delimiter to the encoded string. 
     strBuf.append(curString + ","); 

    } 
    return strBuf.toString(); 
    } 

    /** 
    * Function: decode 
    * -------------------- 
    * Decode an encoded string into its original array.. 
    * 
    * toDecode: the String to be decoded. 
    * 
    * returns: the decoded String array. 
    */ 
    public static String[] decode(String toDecode) 
    { 
    /*We utilize an ArrayList, since the exact number of 
    string elements is inderterminate*/ 
    ArrayList<String> decoded = new ArrayList<String>(); 

    /*Retrieve a representation of the current string element that is 
    easier to modify.*/ 
    StringBuffer encodedStr = new StringBuffer(toDecode); 

    //The starting point of the current isolated string to add/append. 
    int currIndex = 0; 

    for(int i = 0; i < encodedStr.length(); i++) 
    { 
     /*If we see the "break character" remove it, and skip 
     the following character*/ 
     if(encodedStr.charAt(i) == '?') 
     encodedStr.deleteCharAt(i); 

     /*If we see a delimiter, add what we have amassed 
     so far to the list.*/ 
     else if(encodedStr.charAt(i) == ',') 
     { 
     decoded.add(encodedStr.substring(currIndex, i)); 

     //Update the starting point. 
     currIndex = i + 1; 
     } 
    } 

    String[] toReturn = new String[decoded.size()]; 
    return decoded.toArray(toReturn); 
    } 
} 

39号线在EncodeDecode:JAVA:

for(int i = 0; i < toEncode.length; i++) 
+0

你应该看看note_items.xml:是否有一个带有textView2的id的textview?另外savedEntries可能已经在您的代码中被设置为null – donfuxx

+0

当然我检查了是否存在id并且它是正确的。它存在并且它是正确的。我试过也设置了savedEntries string = null,但仍然是相同的崩溃和错误。更明确的说,当应用程序启动时textView应该为空,那么它应该由用户填充值。这不是问题吗?谢谢 !!! – Andrei

+0

和id是“note_items”布局?无论如何在引发NPE的行之前添加一个日志并检查所有值。 – donfuxx

回答

1

根据您的调试savedEntries == null。这是对的NullPointerException这里的原因:savedEntries[position]

既然你说,这些阵列值将由用户提供以后就可以,例如只需添加一个空检查,以避免这个问题,是这样的:

if (savedEntries != null) { 
    holder.text.setText(savedEntries[position]); 
} else { 
    holder.text.setText(""); 
} 

更新:

貌似你试图查找TextView的,在2首不同布局的个XML ID textView2!一个是note_items布局,另一个是note_listview

音符活动

setContentView(R.layout.note_listview); 

    text = (TextView) findViewById(R.id.textView2); 

NoteAdapter

rowView = inflater.inflate(R.layout.note_items, null); 
    holder.tv = (TextView) rowView.findViewById(R.id.textView1); 
    holder.text = (TextView) rowView.findViewById(R.id.textView2); 

==>看也不看在XML布局(你没问题包括: )我可以说这不好。原因是你要么在不同的布局文本查看ID textView2,这是不好的,因为ID必须是唯一的,或textView2只是在note_items布局中丢失。

+0

仍然会崩溃,并在nullpointing其他:'}其他{ \t \t holder.text.setText( “”); ' – Andrei

+0

Uy :-)我是否理解你的评论错误:'savedEntries == null' while text&holder!= null?为了确保能在错误行之前加上这个:'Log.d(“调试NPE”,“text:”+ holder.text +“savedEntries:”+ savedEntries);'让我知道它打印的是什么。因为最后看起来像文本是空的,虽然你说的ID是正确的note_items布局..怪异。 – donfuxx

+0

它看起来像是有效,但我仍然在EncodeDecode活动的第39行获得1个NPE。我无法更改我的共享前导代码,也不能使用此类吗?你能帮我解决吗?非常感谢 ! **我在第一篇文章中编辑并添加了EncodeDecode.java,谢谢! – Andrei

1

lv.setAdapter(new NoteAdapter(this, prgmNameList, null))的问题。 NoteAdapter的构造函数期望第三个参数是程序列表。

此外,我会建议在Note中创建一个空数组,并将其作为NoteAdapter的第二个参数传入。然后,在你onStop,你可以简单地说的String toSave = EncodeDecode.encode(the_array_you_created);代替String toSave = EncodeDecode.encode(adapter.savedEntries);

编辑

public class Note extends Activity { 

... 
private String[] savedArray; 
... 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    ... 
    savedArray = new String[prgmNameList.length]; 
    lv.setAdapter(new NoteAdapter(this, savedArray, prgmNameList)); 

} 

...

@Override 
protected void onStop() { 
    String toSave = EncodeDecode.encode(savedArray); 
    SharedPreferences.Editor editor = getSharedPreferences("LV Data", 
      MODE_PRIVATE).edit(); 
    editor.putString("TVEntries", toSave); 
    editor.commit(); 
} 
.... 

}

+0

我不明白你点。你可以更具体地说明如何创建这个空数组并将其传递给NoteAdapter的第二个参数吗? – Andrei

+0

@Andrei,增加了代码。我的观点是,在我看来,你保存东西的数组是作为NoteAdapter的第二个参数传入的,并且你在活动中初始化的程序列表是第三个参数。 –

+0

这种方式没有工作..谢谢! – Andrei