Android学习日记(2)

来源:互联网 发布:优盘数据恢复实例 编辑:程序博客网 时间:2024/06/05 10:42

在做MarsChen老师的《Android开发视频教学》第一季(非重制版)的时候,第29期做一个Mp3Player的项目。其中需要用到http下载,由于MarsChen老师的Android版本比较低,在主线程中用了http下载请求,会出现NetworkOnMainThreadException异常,这是由于在Android4.0之后,main Thread中不能有网络请求(http,socket),需要新开一个子线程。


java中新开线程的方法有三个:

1、extends Thread

只能继承一个父类,所以当子线程继承了别的父类时候,不能用此方法

2、implements Runnable

优点:可以继承多个父类。限制:只能用于没有返回值的线程

3、implements Callable

必须有返回值。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了。

而在我需要的项目中,既需要将urlStr参数传入子线程,同时需要子类返回值(XML),所以我选择实用第3种方法(好像handler也可以传输数据,以后可以再学习)


示例代码为(摘自http://www.cnblogs.com/linjiqin/archive/2013/07/25/3213809.html):

package cn.thread;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/** * 有返回值多线程 *  * @author 林计钦 * @version 1.0 2013-7-25 上午10:16:43 */public class CallableFutureTest {    public static void main(String[] args) throws ExecutionException, InterruptedException {        CallableFutureTest test = new CallableFutureTest();                // 创建一个线程池        ExecutorService pool = Executors.newFixedThreadPool(2);        // 创建两个有返回值的任务        Callable c1 = test.new MyCallable("A");        Callable c2 = test.new MyCallable("B");                // 执行任务并获取Future对象        Future f1 = pool.submit(c1);        Future f2 = pool.submit(c2);                // 从Future对象上获取任务的返回值,并输出到控制台        System.out.println(">>>" + f1.get().toString());        System.out.println(">>>" + f2.get().toString());                // 关闭线程池        pool.shutdown();    }    class MyCallable implements Callable {        private String oid;        MyCallable(String oid) {            this.oid = oid;        }        public Object call() throws Exception {            return oid + "任务返回的内容";        }    }}

我的Mp3Player中使用的代码为(ThreadPool中只有一个任务):

package gy.mp3player;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import gy.download.HttpDownloader;import android.app.ListActivity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;public class Mp3ListView extends ListActivity {private static final int UPDATE = 1;private static final int ABOUT = 2;    @Overridepublic boolean onCreateOptionsMenu(Menu menu) {// TODO Auto-generated method stub    menu.add(0, UPDATE, 1, R.string.mp3list_update);    menu.add(0, ABOUT, 2, R.string.mp3list_about);return super.onCreateOptionsMenu(menu);}    @Overridepublic boolean onOptionsItemSelected(MenuItem item) {// TODO Auto-generated method stubif(item.getItemId() == UPDATE){String xml;try {xml = downloadXML("http://180.161.177.223:8080/mp3/resources.xml");System.out.println("xml------>" + xml);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ExecutionException e) {// TODO Auto-generated catch blocke.printStackTrace();}}else if(item.getItemId() == ABOUT){}return super.onOptionsItemSelected(item);}private String downloadXML(String urlStr) throws InterruptedException, ExecutionException{//创建一个线程池ExecutorService pool = Executors.newFixedThreadPool(1);//创建一个有返回值的任务Callable c1 = new MyCallable(urlStr);//执行任务并获得Future对象Future f = pool.submit(c1);String xml = f.get().toString();return xml;}class MyCallable implements Callable{private String urlStr;MyCallable(String urlStr){this.urlStr = urlStr;}@Overridepublic Object call() throws Exception {// TODO Auto-generated method stubHttpDownloader httpDownloader = new HttpDownloader();String result = httpDownloader.download(urlStr);return result;}}@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_mp3_list_view);    }    }
其中调用了一个HttpDownloader类,用来执行http请求,代码为:

package gy.download;import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;public class HttpDownloader {private URL url = null;/** * 根据URL下载文件,前提是这个文件当中的内容是文本,函数的返回值就是文件当中的内容 * 1.创建一个URL对象 * 2.通过URL对象,创建一个HttpURLConnection对象 * 3.得到InputStram * 4.从InputStream当中读取数据 * @param urlStr * @return */public String download(String urlStr) {StringBuffer sb = new StringBuffer();String line = null;BufferedReader buffer = null;try {// 创建一个URL对象url = new URL(urlStr);// 创建一个Http连接HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();// 使用IO流读取数据buffer = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));while ((line = buffer.readLine()) != null) {sb.append(line);}} catch (Exception e) {e.printStackTrace();} finally {try {buffer.close();} catch (Exception e) {e.printStackTrace();}}return sb.toString();}}

结果能得到xml文件,并在控制台输出,一天的努力没白费,yeah,明天继续下一步!

0 0