简体   繁体   中英

how to parse json array inside json object retrofit2 mvvm

I have a json that have an object inside that object I have json array i made the pojo but as like for mvvm i cant figure how to parse it and show it in recyclerView (fragment) please check my codes and thanks this is my json

{ 
"response":{ 
  "status":"ok",
  "userTier":"developer",
  "total":2157516,
  "startIndex":1,
  "pageSize":10,
  "currentPage":1,
  "pages":215752,
  "orderBy":"newest",
  "results":[ 
     { 
        "id":"uk-news/2019/dec/02/killer-of-three-elderly-devon-men-found-not-guilty-due-to-insanity",
        "type":"article",
        "sectionId":"uk-news",
        "sectionName":"UK news",
        "webPublicationDate":"2019-12-02T17:53:26Z",
        "webTitle":"Killer of three elderly Devon men found not guilty due to insanity",
        "webUrl":"https://www.theguardian.com/uk-news/2019/dec/02/killer-of-three-elderly-devon-men-found-not-guilty-due-to-insanity",
        "apiUrl":"https://content.guardianapis.com/uk-news/2019/dec/02/killer-of-three-elderly-devon-men-found-not-guilty-due-to-insanity",
        "isHosted":false,
        "pillarId":"pillar/news",
        "pillarName":"News"
     },
     { 
        "id":"football/2019/dec/02/fa-homophobic-chants-west-ham-chelsea-kick-it-out",
        "type":"article",
        "sectionId":"football",
        "sectionName":"Football",
        "webPublicationDate":"2019-12-02T17:53:09Z",
        "webTitle":"FA in discussions after homophobic chants by West Hams fans",
        "webUrl":"https://www.theguardian.com/football/2019/dec/02/fa-homophobic-chants-west-ham-chelsea-kick-it-out",
        "apiUrl":"https://content.guardianapis.com/football/2019/dec/02/fa-homophobic-chants-west-ham-chelsea-kick-it-out",
        "isHosted":false,
        "pillarId":"pillar/sport",
        "pillarName":"Sport"
     },
     { 
        "id":"news/shortcuts/2019/dec/02/jeremy-corbyn-suit-fabric-labour-leader-for-the-many-not-the-few-pinstripes",
        "type":"article",
        "sectionId":"politics",
        "sectionName":"Politics",
        "webPublicationDate":"2019-12-02T17:42:03Z",
        "webTitle":"Socialist pinstripe: the secret message stitched into Jeremy Corbyn’s new suit",
        "webUrl":"https://www.theguardian.com/news/shortcuts/2019/dec/02/jeremy-corbyn-suit-fabric-labour-leader-for-the-many-not-the-few-pinstripes",
        "apiUrl":"https://content.guardianapis.com/news/shortcuts/2019/dec/02/jeremy-corbyn-suit-fabric-labour-leader-for-the-many-not-the-few-pinstripes",
        "isHosted":false,
        "pillarId":"pillar/news",
        "pillarName":"News"
     },
     { 
        "id":"uk-news/2019/dec/02/police-criticised-response-attack-rabbi-in-north-london",
        "type":"article",
        "sectionId":"uk-news",
        "sectionName":"UK news",
        "webPublicationDate":"2019-12-02T17:41:13Z",
        "webTitle":"Police criticised over response to attack on rabbi in north London",
        "webUrl":"https://www.theguardian.com/uk-news/2019/dec/02/police-criticised-response-attack-rabbi-in-north-london",
        "apiUrl":"https://content.guardianapis.com/uk-news/2019/dec/02/police-criticised-response-attack-rabbi-in-north-london",
        "isHosted":false,
        "pillarId":"pillar/news",
        "pillarName":"News"
     },
     { 
        "id":"artanddesign/2019/dec/02/les-tasses-war-and-pissoirs-how-the-debauched-urinals-of-paris-helped-to-beat-the-nazis",
        "type":"article",
        "sectionId":"artanddesign",
        "sectionName":"Art and design",
        "webPublicationDate":"2019-12-02T17:36:28Z",
        "webTitle":"War and pissoirs: how the urinals of Paris helped beat the Nazis",
        "webUrl":"https://www.theguardian.com/artanddesign/2019/dec/02/les-tasses-war-and-pissoirs-how-the-debauched-urinals-of-paris-helped-to-beat-the-nazis",
        "apiUrl":"https://content.guardianapis.com/artanddesign/2019/dec/02/les-tasses-war-and-pissoirs-how-the-debauched-urinals-of-paris-helped-to-beat-the-nazis",
        "isHosted":false,
        "pillarId":"pillar/arts",
        "pillarName":"Arts"
     },
     { 
        "id":"commentisfree/2019/dec/02/trust-in-politics-has-evaporated-now-it-offers-only-fantasy",
        "type":"article",
        "sectionId":"commentisfree",
        "sectionName":"Opinion",
        "webPublicationDate":"2019-12-02T17:36:01Z",
        "webTitle":"Trust in politics has evaporated, now it offers only fantasy | Suzanne Moore",
        "webUrl":"https://www.theguardian.com/commentisfree/2019/dec/02/trust-in-politics-has-evaporated-now-it-offers-only-fantasy",
        "apiUrl":"https://content.guardianapis.com/commentisfree/2019/dec/02/trust-in-politics-has-evaporated-now-it-offers-only-fantasy",
        "isHosted":false,
        "pillarId":"pillar/opinion",
        "pillarName":"Opinion"
     },
     { 
        "id":"film/2019/dec/02/2019-braddies-peter-bradshaw-films-of-the-year",
        "type":"article",
        "sectionId":"film",
        "sectionName":"Film",
        "webPublicationDate":"2019-12-02T17:29:48Z",
        "webTitle":"And the 2019 Braddies go to … Peter Bradshaw's film picks of the year",
        "webUrl":"https://www.theguardian.com/film/2019/dec/02/2019-braddies-peter-bradshaw-films-of-the-year",
        "apiUrl":"https://content.guardianapis.com/film/2019/dec/02/2019-braddies-peter-bradshaw-films-of-the-year",
        "isHosted":false,
        "pillarId":"pillar/arts",
        "pillarName":"Arts"
     },
     { 
        "id":"world/2019/dec/02/christine-lagarde-ecb-should-do-more-to-tackle-climate-emergency",
        "type":"article",
        "sectionId":"world",
        "sectionName":"World news",
        "webPublicationDate":"2019-12-02T17:23:28Z",
        "webTitle":"Lagarde: ECB should do more to tackle climate emergency",
        "webUrl":"https://www.theguardian.com/world/2019/dec/02/christine-lagarde-ecb-should-do-more-to-tackle-climate-emergency",
        "apiUrl":"https://content.guardianapis.com/world/2019/dec/02/christine-lagarde-ecb-should-do-more-to-tackle-climate-emergency",
        "isHosted":false,
        "pillarId":"pillar/news",
        "pillarName":"News"
     },
     { 
        "id":"food/2019/dec/02/robert-neame-obituary",
        "type":"article",
        "sectionId":"food",
        "sectionName":"Food",
        "webPublicationDate":"2019-12-02T17:19:32Z",
        "webTitle":"Robert Neame obituary",
        "webUrl":"https://www.theguardian.com/food/2019/dec/02/robert-neame-obituary",
        "apiUrl":"https://content.guardianapis.com/food/2019/dec/02/robert-neame-obituary",
        "isHosted":false,
        "pillarId":"pillar/lifestyle",
        "pillarName":"Lifestyle"
     },
     { 
        "id":"politics/live/2019/dec/02/general-election-swinson-condemns-johnson-over-trump-friendship-ahead-of-london-visit-live",
        "type":"liveblog",
        "sectionId":"politics",
        "sectionName":"Politics",
        "webPublicationDate":"2019-12-02T17:13:40Z",
        "webTitle":"General election: Johnson insists he opposed early release for terrorists long before London Bridge attack – live news",
        "webUrl":"https://www.theguardian.com/politics/live/2019/dec/02/general-election-swinson-condemns-johnson-over-trump-friendship-ahead-of-london-visit-live",
        "apiUrl":"https://content.guardianapis.com/politics/live/2019/dec/02/general-election-swinson-condemns-johnson-over-trump-friendship-ahead-of-london-visit-live",
        "isHosted":false,
        "pillarId":"pillar/news",
        "pillarName":"News"
     }
  ]
  }
  }

now this is my pojo classes.

public class NewsResponse {

@SerializedName("response")
private NewsArticle response;

public NewsArticle getResponse() {
    return response;
}

public void setResponse(NewsArticle response) {
    this.response = response;
}

 }

public class NewsArticle {

@SerializedName("results")
private List<Result> results = null;

public List<Result> getResults() {
    return results;
}

public void setResults(List<Result> results) {
    this.results = results;
}
 }

public class Result {


    @SerializedName("sectionName")
    private String sectionName;
    @SerializedName("webTitle")
    private String webTitle;
    @SerializedName("webUrl")
    private String webUrl;

public String getSectionName() {
    return sectionName;
}

public void setSectionName(String sectionName) {
    this.sectionName = sectionName;
}

public String getWebTitle() {
    return webTitle;
}

public void setWebTitle(String webTitle) {
    this.webTitle = webTitle;
}

public String getWebUrl() {
    return webUrl;
}

public void setWebUrl(String webUrl) {
    this.webUrl = webUrl;
   }
   }

this is my newrepository

public class NewsRepository {

private static NewsRepository newsRepository;

public static NewsRepository getInstance(){
    if (newsRepository == null){
        newsRepository = new NewsRepository();
    }
    return newsRepository;
}

private NewsApi newsApi;

public NewsRepository(){
    newsApi = RetrofitService.cteateService(NewsApi.class);
}

public MutableLiveData<NewsResponse> getNews(String key){
   final MutableLiveData<NewsResponse> newsData = new MutableLiveData<>();
    newsApi.getNewsList( key).enqueue(new Callback<NewsResponse>() {
        @Override
        public void onResponse(Call<NewsResponse> call,
                               Response<NewsResponse> response) {
            if (response.isSuccessful()){
                newsData.setValue(response.body());
            }
        }

        @Override
        public void onFailure(Call<NewsResponse> call, Throwable t) {
            newsData.setValue(null);
        }
    });
    return newsData;
}
    }

now for the fragment

ublic class NewsFragment extends Fragment {


ArrayList<NewsResponse> articleArrayList = new ArrayList<>();
NewsAdapter newsAdapter;
RecyclerView rvHeadline;

private static final String TAG = "NewsFragment";

private PageViewModel pageViewModel;

public NewsFragment() {
    // Required empty public constructor
}

/**
 * @return A new instance of fragment SpeedDialFragment.
 */
public static NewsFragment newInstance() {
    return new NewsFragment();
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    pageViewModel = ViewModelProviders.of(this).get(PageViewModel.class);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View root = inflater.inflate(R.layout.news_fragment, container, false);
    rvHeadline = root.findViewById(R.id.rvNews);


    pageViewModel.init();
    pageViewModel.getNewsRepository().observe(this, new Observer<NewsResponse>() {
        @Override
        public void onChanged(NewsResponse newsResponse) {
     ** ******      List<NewsArticle> newsArticles = newsResponse.getResponse(); ******
        *******    articleArrayList.addAll(newsArticles);   ********
            newsAdapter.notifyDataSetChanged();
        }
    });

    setupRecyclerView();
    return root;
}
private void setupRecyclerView() {
    if (newsAdapter == null) {
        newsAdapter = new NewsAdapter(getActivity(), articleArrayList);
        rvHeadline.setLayoutManager(new LinearLayoutManager(getActivity()));
        rvHeadline.setAdapter(newsAdapter);
        rvHeadline.setItemAnimator(new DefaultItemAnimator());
        rvHeadline.setNestedScrollingEnabled(true);
    } else {
        newsAdapter.notifyDataSetChanged();
    }
}
   }

well my error is inside pageViewModel.getNewsRepository() i dont know what to do if i change the generic into result class the error fixed in the first line but second line cant accept list from result i'm lost please help

ViewModel class

public class PageViewModel extends ViewModel {

private MutableLiveData<NewsResponse> mutableLiveData;
private NewsRepository newsRepository;

public void init(){
    if (mutableLiveData != null){
        return;
    }
    newsRepository = NewsRepository.getInstance();
    mutableLiveData = newsRepository.getNews( "***************");

}

public LiveData<NewsResponse> getNewsRepository() {
    return mutableLiveData;
}

  }

Directly pass the NewsRepository 's MutableLiveData to View from your ViewModel .

public class PageViewModel extends ViewModel {
    private NewsRepository newsRepository = NewsRepository.getInstance();

    public MutableLiveData<NewsResponse> getNewsRepository() {
        return newsRepository.getNews( "***************");
    }
}

Currently you observe ViewModel's MutableLiveData which is not emits any value. And the data emitted by NewsRepository 's MutableLiveData is lost in ViewModel as it is not observed. You have to maintain single instance of LiveData to observe the changes.

Besides this you have to update your Fragment and Adapter to use List instead of List as your json didn't contain list of article. It contains list of result. Check below

public class NewsFragment extends Fragment {


    ArrayList<Result> ArrayList = new ArrayList<>();

    ....


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        ....

        pageViewModel.getNewsRepository().observe(this, new Observer<NewsResponse>() {
            @Override
            public void onChanged(NewsResponse newsResponse) {
                articleArrayList = newsResponse.getResponse().getResults();
                newsAdapter.notifyDataSetChanged();
            }
        });

        ....

    }

    private void setupRecyclerView() {
        if (newsAdapter == null) {
            newsAdapter = new NewsAdapter(getActivity(), resultArrayList);
            rvHeadline.setLayoutManager(new LinearLayoutManager(getActivity()));
            rvHeadline.setAdapter(newsAdapter);
            rvHeadline.setItemAnimator(new DefaultItemAnimator());
            rvHeadline.setNestedScrollingEnabled(true);
        } else {
            newsAdapter.notifyDataSetChanged();
        }
    }

}

EDIT

I Changed my List into Result

    ArrayList<Result> articleArrayList = new ArrayList<>();

plus i changed it here

 @Override
        public void onChanged(NewsResponse newsResponse) {
            List<Result> newsArticles = newsResponse.getResponse().getResults();
            articleArrayList.addAll(newsArticles);

and like Md.Asaduzzaman said i changed in the adapter too and everything worked

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM