2017-02-21 16 views
1

所以我試圖從我的Firebase數據庫收集數據,將它存儲在ArrayList中,將該ArrayList轉換爲Object數組,然後將其轉換到一個字符串數組。我需要將對象數組轉換爲字符串數組,但它不斷返回空指針

我的代碼非常有效,直到我嘗試將我的ArrayList轉換爲對象數組,然後我得到一個空指針。

public class PostSkillsActivity extends AppCompatActivity { 

    ArrayList<String> skills_array; 
    Object[] mySkills; 
    public String[] skills; 
    private AutoCompleteTextView jobInputSkills; 
    private Button finishBtn; 
    private ImageButton addSkillsBtn; 
    private GridView gridView; 

    private DatabaseReference mDatabaseSkills; 

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

     mDatabaseSkills = FirebaseDatabase.getInstance().getReference().child("Skills"); 
     mDatabaseSkills.keepSynced(true); 
     mDatabaseSkills.addValueEventListener(new ValueEventListener() { 
      @Override 
      public void onDataChange(DataSnapshot dataSnapshot) { 
       collectSkills((Map<String,Object>) dataSnapshot.getValue()); 
      } 

      @Override 
      public void onCancelled(DatabaseError databaseError) {} 
     }); 

     jobInputSkills = (AutoCompleteTextView) findViewById(R.id.input_job_skills); 
     finishBtn = (Button) findViewById(R.id.skills_finish_btn); 
     addSkillsBtn = (ImageButton) findViewById(R.id.add_skills_btn); 

     addSkillsBtn.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       didTapButton(v); 
       addSkill(); 
      } 
     }); 

     /** 
     * Populate Skills Auto Text View 
     */ 
     mySkills = skills_array.toArray(); 
     skills = Arrays.copyOf(mySkills, mySkills.length, String[].class);; 
     ArrayAdapter<String> adapter = new ArrayAdapter<String> 
       (this, android.R.layout.simple_list_item_1, skills); 
     jobInputSkills.setAdapter(adapter); 

     /** 
     * GridView Functionality 
     */ 
     gridView = (GridView) findViewById(R.id.gridview); 
     gridView.setAdapter(new SkillsAdapter(this, skills)); 
     gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
       Toast.makeText(
         getApplicationContext(), 
         ((TextView) view.findViewById(R.id.label)) 
           .getText(), Toast.LENGTH_SHORT).show(); 
      } 
     }); 
    } 

    private void collectSkills(Map<String,Object> skills) { 

     skills_array = new ArrayList<>(); 

     Iterator myVeryOwnIterator = skills.keySet().iterator(); 
     while(myVeryOwnIterator.hasNext()) { 
      String key=(String)myVeryOwnIterator.next(); 
      String value=(String)skills.get(key); 
      skills_array.add(value); 
     } 
    } 

    private void addSkill() { 
     String[] words = jobInputSkills.getText().toString().split(" "); 
     StringBuilder sb = new StringBuilder(); 
     if (words[0].length() > 0) { 
      sb.append(Character.toUpperCase(words[0].charAt(0)) + words[0].subSequence(1, words[0].length()).toString().toLowerCase()); 
      for (int i = 1; i < words.length; i++) { 
       sb.append(" "); 
       sb.append(Character.toUpperCase(words[i].charAt(0)) + words[i].subSequence(1, words[i].length()).toString().toLowerCase()); 
      } 
     } 
     final String skill_name = sb.toString(); 

     if(!TextUtils.isEmpty(skill_name)){ 
      final DatabaseReference newSkill = mDatabaseSkills.child(skill_name); 

      newSkill.child(skill_name).addListenerForSingleValueEvent(new ValueEventListener() { 
       @Override 
       public void onDataChange(DataSnapshot dataSnapshot) { 
        if (dataSnapshot.exists()) { 

        } 
        else { 
         newSkill.setValue(skill_name); 
        } 
       } 

       @Override 
       public void onCancelled(DatabaseError databaseError) {} 
      }); 
     } 
    } 

    public void didTapButton(View view) { 
     ImageButton button = (ImageButton)findViewById(R.id.add_skills_btn); 
     final Animation myAnim = AnimationUtils.loadAnimation(this, R.anim.bounce); 

     // Use bounce interpolator with amplitude 0.2 and frequency 20 
     MyBounceInterpolator interpolator = new MyBounceInterpolator(0.2, 20); 
     myAnim.setInterpolator(interpolator); 

     button.startAnimation(myAnim); 
    } 

    public class SkillsAdapter extends BaseAdapter { 
     private Context context; 
     private final String[] skillValues; 

     public SkillsAdapter(Context context, String[] skillValues) { 
      this.context = context; 
      this.skillValues = skillValues; 
     } 

     public View getView(int position, View convertView, ViewGroup parent) { 

      LayoutInflater inflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

      View gridView; 

      if (convertView == null) { 

       gridView = new View(context); 

       // get layout from mobile.xml 
       gridView = inflater.inflate(R.layout.skills_item, null); 

       // set value into textview 
       TextView textView = (TextView) gridView 
         .findViewById(R.id.label); 
       textView.setText(skillValues[position]); 

       // set image based on selected text 
       ImageView imageView = (ImageView) gridView 
         .findViewById(R.id.remove_skill_btn); 

       String skill = skillValues[position]; 

      } else { 
       gridView = (View) convertView; 
      } 

      return gridView; 
     } 

     @Override 
     public int getCount() { 
      return skillValues.length; 
     } 

     @Override 
     public Object getItem(int position) { 
      return null; 
     } 

     @Override 
     public long getItemId(int position) { 
      return 0; 
     } 

    } 
} 

這是我的Firebase數據庫。我需要將數組中的所有值存儲在數組中以填充AutoTextView。

Skills: 
Android:"Android" 
C++ Programming:"C++ Programming" 
Carpentry:"Carpentry" 
Electrician:"Electrician" 
HTML:"HTML" 
Housework:"Housework" 

更新: 錯誤是與

mySkills = skills_array.toArray(); 

的skills_array開始應該從功能上包含的值

private void collectSkills(Map<String,Object> skills) { 

      skills_array = new ArrayList<>(); 

      Iterator myVeryOwnIterator = skills.keySet().iterator(); 
      while(myVeryOwnIterator.hasNext()) { 
       String key=(String)myVeryOwnIterator.next(); 
       String value=(String)skills.get(key); 
       skills_array.add(value); 
      } 
     } 

我是下面的日誌線78。

02-21 20:34:32.647 4153-4153/com.example.android.oddjobs E/AndroidRuntime: FATAL EXCEPTION: main 
Process: com.example.android.oddjobs, PID: 4153 
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.oddjobs/com.example.android.oddjobs.PostSkillsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object[] java.util.ArrayList.toArray()' on a null object reference 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2572) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2654) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488) 
at android.os.Handler.dispatchMessage(Handler.java:111) 
at android.os.Looper.loop(Looper.java:207) 
at android.app.ActivityThread.main(ActivityThread.java:5728) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679) 
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object[] java.util.ArrayList.toArray()' on a null object reference 
at com.example.android.oddjobs.PostSkillsActivity.onCreate(PostSkillsActivity.java:78) 
at android.app.Activity.performCreate(Activity.java:6301) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1113) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2519) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2654)  
at android.app.ActivityThread.-wrap11(ActivityThread.java)  
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488)  
at android.os.Handler.dispatchMessage(Handler.java:111)  
at android.os.Looper.loop(Looper.java:207)  
at android.app.ActivityThread.main(ActivityThread.java:5728)  
at java.lang.reflect.Method.invoke(Native Method)  
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)  
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)  
02-21 20:34:34.022 4153-4239/com.example.android.oddjobs 

E/NativeCrypto: ssl=0xaf9bb6c0 cert_verify_callback x509_store_ctx=0x9a87820c arg=0x0 
    02-21 20:34:34.022 4153-4239/com.example.android.oddjobs E/NativeCrypto: ssl=0xaf9bb6c0 cert_verify_callback calling verifyCertificateChain authMethod=ECDHE_RSA 
+1

請添加堆棧跟蹤。 – markers

+0

感謝您的評論。我只是修復了這個帖子。 –

+0

什麼是PostSkillsActivity.java的第78行? –

回答

1

Firebase中的ValueListeners是異步的,這意味着它們不會阻止添加它們的代碼。在你的代碼中,它看起來像是在假定監聽器會立即被調用。相反,實際發生的情況是,添加偵聽器後,您的onCreate方法仍在繼續,這意味着在訪問它時,skills_array保持未初始化(空)。

您應該等到偵聽器實際被調用才能使用從中收集的數據更新您的UI。你不能在onCreate中這樣做。

+0

同步與異步並不是真正的問題。瞭解事件和聽衆是。 (只需在這裏選擇措辭...您的答案的內容通常是正確的。) –

+0

Firebase文檔的作者認爲從一開始就注意到這是一個重要的區別:「Firebase數據寫入Firebase數據庫引用並檢索通過將異步偵聽器附加到引用「。 https://firebase.google.com/docs/database/android/read-and-write –

+0

好的,謝謝你的反饋。我如何確保首先調用ValueEventListener。到目前爲止,我試着移動代碼來更新數據到onStart()方法和函數collectSkills,但它還沒有工作。 –

相關問題