2017-12-02 95 views
0

我正在使用OkHttp獲取HTML字符串並在RecyclerView中的片段中列​​出信息。片段中的同步呼叫在第一次啓動時沒有運行並且獲取錯誤數據

但是,當應用程序運行時,首次啓動時不顯示列表信息。

當我點擊其他片段頁面並返回到這個片段頁面後,它顯示列表。

但是當我向下滑動以查看更多列表時,該列表重複兩次(或更多次?)和項目背景顏色混亂。

我該如何解決?謝謝!

我的適配器

public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> { 
    private List<NewsModel> mNewsList; 
    class ViewHolder extends RecyclerView.ViewHolder { 
     TextView newsNameText; 
     TextView newsDataText; 
     View listView; 
     public ViewHolder(View newsView) { 
      super(newsView); 
      newsNameText = (TextView) newsView.findViewById(R.id.news_Name); 
      newsDataText = (TextView) newsView.findViewById(R.id.news_Data); 
      listView = newsView; 
     } 
    } 
    public NewsAdapter(List<NewsModel> newsList) { 
     mNewsList = newsList; 
    } 
    @Override 
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false); 
     final ViewHolder holder = new ViewHolder(view); 
     return holder; 
    } 
    public void setData(List<NewsModel> viewData) { 
     mNewsList.clear(); 
     mNewsList.addAll(viewData); 
     notifyDataSetChanged(); 
    } 
    @Override 
    public void onBindViewHolder(ViewHolder holder, int position) { 
     NewsModel news = mNewsList.get(position); 
     holder.setIsRecyclable(true); 
     if(position % 2 == 0){ 
      holder.listView.setBackgroundColor(0x80E0EEEE); 
     } 
     holder.newsNameText.setText(news.getName()); 
     holder.newsDataText.setText(news.getData()); 
    } 
    @Override 
    public int getItemCount() { 
     return mNewsList.size(); 
    } 

} 

我的片段

public class NewsFragment extends Fragment { 
    List<NewsModel> resultList = new ArrayList<>(); 
    List<NewsModel> htmlList = new ArrayList<>(); 
    NewsAdapter adapter; 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View newsView = inflater.inflate(R.layout.fragment_news, container, false); 
     RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list); 
     LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); 
     newsRecyclerView.setLayoutManager(layoutManager); 
     adapter = new NewsAdapter(getNews()); 
     newsRecyclerView.setAdapter(adapter); 
     return newsView; 

    } 
    private List<NewsModel> getNews() { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        OkHttpClient client = new OkHttpClient(); 
        Request request = new Request.Builder() 
          .url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true") 
          .build(); 
        Response response = client.newCall(request).execute(); 
        String resultString = response.body().string(); 
        resultList.clear(); 
        resultList.addAll(getResult(resultString)); 
        adapter.notifyDataSetChanged(); 
        /*new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { 
         @Override 
         public void run() { 
          adapter.setData(resultList); 
          adapter.notifyDataSetChanged(); 
         } 
        });//postdelayed (runnable long) cannot be applied to runnable*/ 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }).start(); 
     return resultList; 
    } 

    private List<NewsModel> getResult(final String response) { 
     XXXXXX 
     return htmlList; 
    } 
} 
+0

首先,Okhttp不應該在像這樣的線程中運行。使用'client.newCall(request).enqueue' –

回答

1

的問題是,也許你正在添加許多條目,因爲recyclerview試圖重用這些意見,而不是再次重新劃分和再次這導致有時看法不一致。這是問題discussed如果您遇到同樣的問題,請查看它。 禁用它或者啓用它在你的bindViewHolder(

setIsRecyclable(Boolean enable)

使用和你的第二個問題是,onCreateView()從另一個片段回來造成加時被稱爲第二次再次複製數據,因此您需要在添加任何新條目之前清除列表,並且爲什麼它在第一次運行時不顯示,因爲您已經在另一個線程中添加了數據並且沒有更新適配器。

List<NewsModel> resultList = new ArrayList<>(); 
NewsAdapter adapter ; 
public class NewsFragment extends Fragment { 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    View newsView = inflater.inflate(R.layout.fragment_news, container, false); 
    RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list); 
    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); 
    newsRecyclerView.setLayoutManager(layoutManager); 
    adapter = new NewsAdapter(resultList); 
    newsRecyclerView.setAdapter(adapter); 
    getNews(); 
    return newsView; 
} 

    private void getNews(){ 
     AsyncTask<Void,Void,String> asyncTask = new AsyncTask<Void, Void, String>() { 
      @Override 
      protected String doInBackground(final Void... voids) { 
       String resultString = null; 
       OkHttpClient client = new OkHttpClient(); 
       Request request = new Request.Builder() 
         .url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true") 
         .build(); 
       Response response = null; 
       try { 
        response = client.newCall(request).execute(); 
        resultString = response.body().string(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 

       return resultString; 
      } 

      @Override 
      protected void onPostExecute(final String resultString) { 
       super.onPostExecute(resultString); 
       resultList.clear(); 
       resultList.addAll(getResult(resultString)); 
       adapter.notifyDataSetChanged(); 
      } 
     }.execute(); 
    } 
+0

謝謝。我已經嘗試過你的方法。但是這個清單變成了空白......無論我嘗試過什麼。 –

+0

嗨@ AlexLi空列表的原因是我忘了在onCreateView()中調用getNews()。所以你現在可以檢查我已經更新了我的答案,還包括一個加載新聞數據的異步任務,這比我們以前做的更好。 –

+0

相應地更新您的getNews()並在onCreatView()中調用getNews()以查看更改。讓我知道你是否有任何問題。 –

0

線程將改變一些延遲resultList,但在此之前,已經通過舊數據。 請嘗試以下...

public class NewsFragment extends Fragment { 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    View newsView = inflater.inflate(R.layout.fragment_news, container, false); 
    RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list); 
    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); 
    newsRecyclerView.setLayoutManager(layoutManager); 
    getNews(newsRecyclerView); 
    return newsView; 
} 

private void getNews(final RecyclerView newsRecyclerView){ 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       OkHttpClient client = new OkHttpClient(); 
       Request request = new Request.Builder() 
         .url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true") 
         .build(); 
       Response response = client.newCall(request).execute(); 
       String resultString = response.body().string(); 
       List<NewsModel> resultList = getResult(resultString); 
       NewsAdapter adapter = new NewsAdapter(resultList); 
       newsRecyclerView.setAdapter(adapter); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }).start(); 
} 

private List<NewsModel> getResult(final String response) { 
    XXXXXXXXX 
    return List; 
} 
0

主要模式是壞的。 此代碼最簡單的方法是在適配器下載並調用notifyDataSetChanged()時設置(不添加)適配器中的項目 - 所有單元格都將重繪。

所以使適配器字段,添加方法適配器使用setData()和:

... 
Response response = client.newCall(request).execute(); 
String resultString = response.body().string(); 
resultList = getResult(resultString); 
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      adapter.setData(results); 
      adapter.notifyDataSetChanged(); 
     } 
    }); 
+0

你不需要一個單獨的setData方法。這個答案是內建模式。 https://stackoverflow.com/a/47610769/2308683 –

+0

@ mac229 new Handler Alerted:postdelayed(runnable long)無法應用於可運行 –

+0

@ cricket_007我嘗試過vikas的方法。該列表是空的。 –

相關問題