2017-12-02 1 views
0

OkHttp를 사용하여 HTML 문자열을 가져오고 RecyclerView의 정보를 단편에 나열합니다.Fragment의 동기 호출이 처음 시작될 때 실행되지 않고 오류 데이터가 발생합니다.

그러나 앱을 실행하면 처음 실행될 때 목록 정보가 표시되지 않았습니다.

다른 프래그먼트 페이지를 클릭하고이 프래그먼트 페이지로 돌아 가면 해당 목록이 표시됩니다.

하지만 더 많은 목록을보기 위해 아래로 스 와이프하면 목록이 두 번 이상 반복되고 항목 배경색이 흐트러집니다.

내가 그것을 어떻게 를 해결할 수 있습니까? 감사!

내 어댑터

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

우선 Okhp는 다음과 같이 스레드로 실행하면 안됩니다. '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 처리기 경고 : 게시 지연 (runnable long)을 실행할 수 없습니다. –

+0

@ cricket_007 vikas의 방법을 시도했습니다. 목록이 비어 있습니다. –

관련 문제