2017-02-21 48 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,但它还没有工作。 –

相关问题