-3

當我的應用程序嘗試獲取適配器上的位置時,它崩潰了,因爲顯然我的適配器未正確填充。爲什麼我的應用程序崩潰時出現NullPointerException,爲什麼我的適配器(可能)爲空?

數據通過Retrofit正常運行,我的自定義適配器(基於ArrayAdapter的NewsAdapter)之前已經被填充,但我必須對其進行一些調整,現在我無法完成它的工作。

想法是獲取每個新聞源,獲取每個特定新聞源的文章,然後用這些文章填充我的GridView。這裏是我的代碼:

NewsAdapter

public class NewsAdapter extends ArrayAdapter<Articles_Map> { 
    Context mContext; 
    ArrayList<Articles_Map> articles; 

    public NewsAdapter(Context c, int resource) { 
     super(c, resource); 
     this.mContext = c; 
    } 

    public NewsAdapter(Context c, int resource, ArrayList<Articles_Map> articles) { 
     super(c, resource, articles); 
     this.mContext = c; 
     this.articles = articles; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     // get the property we are displaying 
     Articles_Map article = articles.get(position); 

     // get the inflater and inflate the XML layout for each item 
     LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 
     View view = inflater.inflate(R.layout.article_layout, null); 

     ImageView thumbnail = (ImageView) view.findViewById(R.id.thumbnail); 
     TextView title = (TextView) view.findViewById(R.id.title); 
     TextView description = (TextView) view.findViewById(R.id.description); 

     Picasso.with(mContext).load(article.urlToImage).into(thumbnail); 
     title.setText(article.title); 
     description.setText(article.description); 

     return view; 
    } 
} 

NewsAPI_Map

public class NewsAPI_Map { 
    String status; 
    String source; 
    ArrayList<Articles_Map> articles; 

    public NewsAPI_Map(String status, String source, ArrayList<Articles_Map> articles) { 
     this.status = status; 
     this.source = source; 
     this.articles = articles; 
    } 
} 

Articles_Map

public class Articles_Map { 
    String title; 
    String description; 
    String url; 
    String urlToImage; 

    public Articles_Map(String title, String description, String url, String urlToImage) { 
     this.title = title; 
     this.description = description; 
     this.url = url; 
     this.urlToImage = urlToImage; 
    } 
} 

ListNewsActivity.java

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    /* ... */ 

    // parameters for Sources endpoint 
    String category = "sport"; 
    String language = "en"; 
    String country = "us"; 

    // Sources endpoint 
    Sources_Interface client_sources = NewsAPI_Adapter.createService(Sources_Interface.class); 
    Call<Sources_Map> call_sources = client_sources.getData(category, language, country); 

    call_sources.enqueue(new Callback<Sources_Map>() { 
     @Override 
     public void onResponse(Call<Sources_Map> call_sources, Response<Sources_Map> response) { 
      if (response.body() != null) { 
       final NewsAdapter nAdapter = new NewsAdapter(ListNewsActivity.this, 
         R.layout.article_layout); 

       for (Sources_Content source : response.body().sources) { 
        if (source.sortBysAvailable.contains("latest")) { 
         // Articles endpoint 
         NewsAPI_Interface client = NewsAPI_Adapter.createService(NewsAPI_Interface.class); 
         Call<NewsAPI_Map> call = client.getData(source.id, "apiKeyHere"); 

         call.enqueue(new Callback<NewsAPI_Map>() { 
          @Override 
          public void onResponse(Call<NewsAPI_Map> call, Response<NewsAPI_Map> response) { 
           if (response.body() != null) { 
            ExpandableHeightGridView gv_content = (ExpandableHeightGridView) findViewById(R.id.gv_content); 
            nAdapter.addAll(response.body().articles); 
            System.out.println("Count: " + nAdapter.getCount() + "\n" + 
              "Body: " + response.body().articles + "\n"); 
            gv_content.setAdapter(nAdapter); 
            gv_content.setExpanded(true); 
           } 
          } 

          @Override 
          public void onFailure(Call<NewsAPI_Map> call, Throwable t) { 
           System.out.println("An error ocurred!\n" + 
             "URL: " + call.request().url() + "\n" + 
             "Cause: " + t.getCause().toString()); 
          } 
         }); 
        } 
       } 
      } 
     } 

     @Override 
     public void onFailure(Call<Sources_Map> call_sources, Throwable t) { 
      System.out.println("An error ocurred!"); 
     } 
    }); 
} 

日誌:

E/AndroidRuntime: FATAL EXCEPTION: main 
        Process: pt.ismai.a26800.readr, PID: 8398 
        java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.util.ArrayList.get(int)' on a null object reference 
         at pt.ismai.a26800.readr.NewsAdapter.getView(NewsAdapter.java:38) 
         at android.widget.AbsListView.obtainView(AbsListView.java:2346) 
         at android.widget.GridView.onMeasure(GridView.java:1065) 
         at pt.ismai.a26800.readr.ExpandableHeightGridView.onMeasure(ExpandableHeightGridView.java:37) 
         at android.view.View.measure(View.java:18804) 
         at android.support.v4.widget.NestedScrollView.measureChildWithMargins(NestedScrollView.java:1411) 
         at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 
         at android.support.v4.widget.NestedScrollView.onMeasure(NestedScrollView.java:479) 
         at android.view.View.measure(View.java:18804) 
         at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 
         at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:700) 
         at android.support.design.widget.HeaderScrollingViewBehavior.onMeasureChild(HeaderScrollingViewBehavior.java:90) 
         at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onMeasureChild(AppBarLayout.java:1364) 
         at android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:765) 
         at android.view.View.measure(View.java:18804) 
         at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 
         at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 
         at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135) 
         at android.view.View.measure(View.java:18804) 
         at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 
         at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465) 
         at android.widget.LinearLayout.measureVertical(LinearLayout.java:748) 
         at android.widget.LinearLayout.onMeasure(LinearLayout.java:630) 
         at android.view.View.measure(View.java:18804) 
         at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 
         at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 
         at android.view.View.measure(View.java:18804) 
         at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 
         at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465) 
         at android.widget.LinearLayout.measureVertical(LinearLayout.java:748) 
         at android.widget.LinearLayout.onMeasure(LinearLayout.java:630) 
         at android.view.View.measure(View.java:18804) 
         at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954) 
         at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 
         at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2643) 
         at android.view.View.measure(View.java:18804) 
         at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2112) 
         at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1228) 
         at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1464) 
         at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1119) 
         at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6060) 
         at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858) 
         at android.view.Choreographer.doCallbacks(Choreographer.java:670) 
         at android.view.Choreographer.doFrame(Choreographer.java:606) 
         at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844) 
         at android.os.Handler.handleCallback(Handler.java:746) 
         at android.os.Handler.dispatchMessage(Handler.java:95) 
         at android.os.Looper.loop(Looper.java:148) 
         at android.app.ActivityThread.main(ActivityThread.java:5443) 
         at java.lang.reflect.Method.invoke(Native Method) 
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
+0

請發佈日誌。 – Enzokie

+0

@Enzokie我是新開發的Android開發人員,但我假設你的意思是控制檯輸出的日誌,所以我將它添加到了我的原始文章中。如果你的意思是你還有其他事情,就問。 – KaiZ

回答

0

你基本上是使用第一個構造函數,這意味着你需要通過你的ArrayList<Articles_Map>。使用你的第一個構造函數會導致你的Array未初始化,並導致你的Nullpointer Exception

final NewsAdapter nAdapter = new NewsAdapter(ListNewsActivity.this, 
         R.layout.article_layout); 

雖然您的要求是第二個。

public NewsAdapter(Context c, int resource, ArrayList<Articles_Map> articles) { 
     super(c, resource, articles); 
     this.mContext = c; 
     this.articles = articles; 
    } 

您需要通過提供ArrayList<Articles_Map>實例來使用其他重載的構造函數,例如,

final NewsAdapter nAdapter = new NewsAdapter(ListNewsActivity.this, 
          R.layout.article_layout, articles); 

更新代碼

public class NewsAdapter extends ArrayAdapter<Articles_Map> { 
    Context mContext; 
    ArrayList<Articles_Map> articles; 

    public NewsAdapter(Context c, int resource) { 
     super(c, resource); 
     this.mContext = c; 
     this.articles = new ArrayList<>(); 
    } 

    public void add(Articles_Map m){ 
     articles.add(m); 
     notifyDataSetChanged(); 
    } 

    ... more code ... 
} 

我添加的代碼add(Articles_Map m),這樣就可以在回調使用它,在這種情況下,你不需要重新初始化適配器。

+0

是的,我知道,並且該構造函數是我在更改之前使用的構造函數,並且所有內容都正常工作。然而,據我所知,我目前不能使用相同的構造函數,因爲如果我聲明變量並在onResponse()中使用3參數構造函數,它將繼續爲同一變量聲明,因爲它位於循環,這是一個問題。我看不出如何解決這個問題。 – KaiZ

+0

其實你應該聲明你的適配器爲成員變量,你需要在這裏接受'Articles_Map'參數然後'無效'視圖的方法。 – Enzokie

+0

對不起,但我不完全明白你的意思......你能澄清你的意思嗎?「接受Articles_Map參數的方法,然後'視圖無效'。」? – KaiZ

0

問題是,您正在使用第一個構造函數創建適配器,該構造函數並未初始化數據集(數組列表),因此它爲空。然後,您嘗試將數據添加到您的數據集「文章」,由於未初始化,這些數據集將不起作用。

要解決這個問題,請進入您在此處定義的addAll()方法 nAdapter.addAll(response.body()。articles);

並添加在您的方法的開頭 if(articles == null)articles = new ArrayList articles(); }

之後,別忘了打電話。notifyDataHasChanged();

,這是一個基本的編程規則,你應該知道,雖然收藏品均不是Android的東西

+0

我實際上並沒有定義過addAll()方法,但我現在還是隻做了一個。我把它編碼爲[this](https://gist.github.com/KaiZ51/a3f7b1abcdfcb9acad3fe3f2ca9d346f),我不確定這是否正確。該應用程序現在不會崩潰,但它似乎沒有填充適配器,因爲沒有任何顯示,並且我的getCount()始終爲0。 – KaiZ

+0

http://stackoverflow.com/a/5092426/3325970這應該回答你的問題 – Makaveli

0
Articles_Map article = articles.get(position); 

記住在使用前要檢查空:

if (articles != null) 
{ 
    Articles_Map article = articles.get(position); 
    //other code 
} 

在您NewsAPI_Map類,你忘記把吸氣劑&二傳手爲你的對象。

NewsAPI_Map: 

public class NewsAPI_Map { 
    String status; 
    String source; 
    ArrayList<Articles_Map> articles; 

    public NewsAPI_Map(String status, String source, ArrayList<Articles_Map> articles) { 
     this.status = status; 
     this.source = source; 
     this.articles = articles; 
    } 

    public void setStatus(String status){ 
     this.status = status; 
    } 

    public String getStatus(){ 
     return this.status; 
    } 
    .... 
} 

願你安息API無法數據轉換成你的對象,因爲你的類的getter &二傳手。

相關問題