2

所以我试图通过从 youtube 频道检索 json 数据来制作一个 youtube 应用程序。问题是我很擅长编写单线程应用程序。但是当谈到多线程时,我总是失去洞察力。

我还没有在学校学过,大多数教程都是垃圾,或者至少我发现了。

所以我想要做的是在我的“GetVideos”类中引入一个线程,这样它就不会在检索视频时减慢我的应用程序的速度。我知道我必须使用处理程序和线程,但每次我尝试使用它们时,我的应用程序都会崩溃。你们能帮忙吗?

public class GetVideos { //class that retrieves JSON data based on youtube username

private String channelName;
private HttpClient client; //client that gets info
private VideoLibrary lib;


public GetVideos(String channelName) {
    this.channelName = channelName;
    client = new DefaultHttpClient();
    lib = new VideoLibrary();
    fillData();
}

private void fillData() {
    try {
        final String URL = "http://gdata.youtube.com/feeds/api/users/" + channelName + "/uploads?v=2&alt=jsonc";
        HttpGet get = new HttpGet(URL);
        HttpResponse response = client.execute(get);
        String jsonString = EntityUtils.toString(response.getEntity());
        JSONObject json = new JSONObject(jsonString);
        JSONArray jsonArray = json.getJSONObject("data").getJSONArray("items");
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject items = jsonArray.getJSONObject(i);
            String title = items.getString("title");
            String thumbUrl = items.getJSONObject("thumbnail").getString("sqDefault");
            String url = items.getJSONObject("player").getString("default");
            lib.addVideo(new Video(title, url, thumbUrl));

        }

    } catch (JSONException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (ClientProtocolException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (IOException e) {
        e.printStackTrace();  
       }
   }

    public VideoLibrary getLib() {
         return lib;
    } 
 }

public class SxePhil extends Activity { //class that makes up the interactive end of
//the app, here the JSON data is put in a list 
private ListView list;
private GetVideos g;
private VideoLibrary videoLibrary;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.sxephil);
    list = (ListView) findViewById(R.id.sxephilList);
    g = new GetVideos("sxephil");
    videoLibrary = g.getLib();

    ArrayList<String> titles = new ArrayList<String>();
    for (int i = 0; i < 25; i++) {
        titles.add(videoLibrary.getVideos().get(i).getTitle());
    }


       ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.simplerow, titles);
        list.setAdapter(adapter);
   }  
}

基本上我尝试的是实现这里使用的线程:http: //blog.blundell-apps.com/show-youtube-user-videos-in-a-listview/

在我的代码中,因为这个项目是建立在一个较旧的 sdk 上的,所以我想对其进行现代化改造。看看 GetYoutube*** 类和 MainActivity 类,这就是钱的所在

4

3 回答 3

0

您可以使用 AsyncTask 最轻松地完成此操作。看看这个教程。

http://android-developers.blogspot.com/2009/05/painless-threading.html

于 2012-08-23T21:50:38.273 回答
0

您应该使用AsyncTask甚至更好的Loader,它们会自动为您处理踏板

于 2012-08-23T21:41:53.233 回答
0

第一:基本建议(您必须记住并遵循)

  • 永远不要在类构造函数中进行处理(这是糟糕的 OO 设计,恕我直言)
  • 永远不要在 Activity.onCreate 方法留下耗时的过程(一般来说,在 UI 线程运行的任何方法中,即 onResume()、onClick()、...)

mario 和 runor49 是对的:您应该在这里使用 AsyncTask (并且您必须阅读并理解http://developer.android.com/guide/components/processes-and-threads.html#WorkerThreads。如果您不这样做,请阅读又来了……)

基本上,您应该执行以下操作:

  1. onCreate 必须启动一个单独的线程,该线程将包含“长”处理(从网络加载数据)
  2. 完成后,该线程必须调用 Activity.runOnUiThread(Runnable),其中 runnable 将创建 Adapter 并将其分配给 ListView。

这是一个代码示例:

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    loadDataInThread();
    }

private void loadDataInThread() {
    new Runnable() {            
        @Override
        public void run() {
            // LOAD DATA FROM NETWORK
            displayDataInUIThread(datas);
            }
        }.start();
    }       

private void displayDataInUIThread(final VideoLibrary data) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.simplerow, data);
            list.setAdapter(adapter);
        }
    });
}

这是一种非常基本(且粗鲁)的方式,AsyncTask方式()方式会好得多,但它应该可以工作并履行合同......

于 2012-08-23T21:43:16.287 回答