2015-12-17 192 views
0

我有一個片段類,描述RecyclerView。創建元素需要arrayarray通過解析JSON而形成。當我使用良好的互聯網連接時,一切正常,並且我可以看到理想的項目列表。但使用低速連接我的UI是空的。同步線程

我意識到threads存在一些問題,但我沒有足夠的知識來解決我的問題。

下面是一個代碼:

public class ListVideo extends Fragment { 
private int loadLimit = 9; 
private RecyclerView recyclerView; 
private RecyclerAdapter adapter; 
private LinearLayoutManager linearLayoutManager; 
final OkHttpClient client = new OkHttpClient(); 
List<VideoData> videoList; 
List<String> videoDataList; 
JSONArray json_array_list_of_videos; 
int counter = 0; 
int offset; 

@Override 
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 
         @Nullable Bundle savedInstanceState) { 
    return inflater.inflate(R.layout.listvideofragment, container, false); 
} 

@Override 
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    videoList = new ArrayList<>(); 
    videoDataList = new ArrayList<>(); 
    recyclerView = (RecyclerView) view.findViewById(R.id.list); 

    loadData(offset); 
    createRecycleView(); 
    recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(
      linearLayoutManager) { 
     @Override 
     public void onLoadMore(int offset) { 
      // do somthing... 

      loadMoreData(offset); 

     } 

    }); 


} 

private void loadMoreData(int offset) { 

    loadLimit += 10; 
    loadData(offset); 

    adapter.notifyDataSetChanged(); 

} 

private void loadData(final int offset) { 
    try { 
     Request request = new Request.Builder() 
       .url("http://video.motti.be/api/video.getVideoList?offset=" + 
         offset 
         + "&limit=20") 
       .build(); 

     client.newCall(request).enqueue(new Callback() { 
      @Override 
      public void onFailure(Request request, IOException throwable) { 
       throwable.printStackTrace(); 
      } 

      @Override 
      public void onResponse(Response response) throws IOException { 
       try { 
        if (!response.isSuccessful()) 
         throw new IOException("Unexpected code " + response); 

        Headers responseHeaders = response.headers(); 
        for (int i = 0; i < responseHeaders.size(); i++) { 
         System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); 
        } 

        String json_string_obj = response.body().string(); 
        JSONObject url = new JSONObject(json_string_obj); 
        json_array_list_of_videos = url.getJSONArray("data"); 
        System.out.println(json_array_list_of_videos.toString()); 
        for (int y = 0; y <= 9; y++) { 
         if (json_array_list_of_videos.get(y).toString().equals("A9knX0GXrg")) { 
          videoDataList.add("6kS9Tt1e47g"); 
         } else { 
          videoDataList.add(json_array_list_of_videos.get(y).toString()); 
          System.out.println("++++++" + json_array_list_of_videos.get(y).toString()); 
         } 
        } 
        for (int i = counter; i <= loadLimit; i++) { 
         if (videoDataList == null) { 
          return; 
         } else { 
          VideoData next_queue_id = new VideoData(videoDataList.get(i)); 
          videoList.add(next_queue_id); 
          counter++; 

         } 
        } 


       } catch (Exception e) { 
        e.printStackTrace(); 
       } 

      } 
     }); 

    } catch (ArrayIndexOutOfBoundsException e) { 
     e.printStackTrace(); 

    } 

} 

public void createRecycleView() { 

    adapter = new RecyclerAdapter(videoList, getContext()); 
    linearLayoutManager = new LinearLayoutManager(getActivity()); 
    linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); 
    recyclerView.setHasFixedSize(true); 
    recyclerView.setLayoutManager(linearLayoutManager); 
    recyclerView.setAdapter(adapter); 
} 
} 

我明白了,我得到Response後即可new adapter creates.For知識的缺乏,因爲我悲傷,我不知道如何使threadonResponse方法等待。

希望你不會覺得這個問題太沉悶或愚蠢,並會幫助我。

預先感謝您!

回答

0

您需要在修改其列表(videoList)後通知適配器。

目前loadMoreData(int offset)方法不能保證,因爲loadData(offset);方法可以在列表被修改之前返回(請求被異步處理)。

你可以做的是這樣的:

loadMoreData(int offset)方法取出adapter.notifyDataSetChanged();語句,並把它添加到onResponse(Response response)方法。

實施例:

@Override 
public void onResponse(Response response) throws IOException { 
    try { 
     ... 
     for (int i = counter; i <= loadLimit; i++) { 
      if (videoDataList == null) { 
       return; 
      } else { 
       VideoData next_queue_id = new VideoData(videoDataList.get(i)); 
       videoList.add(next_queue_id); 
       counter++; 
      } 
     } 
     ListVideo.this.runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       adapter.notifyDataSetChanged(); 
      } 
     }); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

這種方法可以產生其他問題,因爲videoList可由多個線程同時進行修改。您需要找到一種方法來同步訪問此列表或使用線程安全列表。

+0

非常感謝,@Titus! 'runOnUiThread'出現了一些問題,所以我使用了'new Handler(Looper.getMainLooper())',它解決了!再次感謝你! –

+0

@PeterParker我很高興我能幫上忙,祝你好運。 – Titus