2017-12-02 6 views
0

OkHttpを使用してHTML文字列を取得し、RecyclerViewの情報をフラグメントにリストします。最初の起動時にフラグメントの同期呼び出しが実行されず、エラーデータが返される

ただし、アプリを実行すると、最初の起動時にリスト情報が表示されませんでした。

他のフラグメントページをクリックしてこのフラグメントページに戻ると、それが表示されます。

しかし、もっと多くのリストを見るためにスワイプすると、リストは2回以上繰り返され、アイテムの背景色が乱れることがあります。

どうすれば修正できますか?ありがとう!

マイアダプタ

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新しいハンドラ警告:実行可能ファイルにポスト遅延(runnable long)を適用できません –

+0

@ cricket_007私はvikasの方法を試しました。リストは空です。 –

関連する問題