Android基础总结.doc(第五节、多线程下载、activity声明周期、意图操作)

来源:互联网 发布:武汉淘宝摄影 编辑:程序博客网 时间:2024/06/06 11:36

作者:韩亚飞_yue31313_韩梦飞沙 QQ:313134555


第一节、  多线程下载、activity声明周期、意图操作

一、知识概括

1、多线程下载

2、ANR异常处理及、Hanlder消息处理机制

3、Intent意图

4、Ancivity声明周期

二、知识总结

1、多线程断点下载

1)多线程下载原理

多线程下载原理:通过在本地设置一个个和服务器上大小一致的文件。然后开启多个线程,分别设置每个线程下载开始和结束的数据,形成多点同时下载一个数据流,从而提高了下载效率。

RandomAccessFile file = newRandomAccessFile(

                                                        "/mnt/sdcard/"+ getFilenName(path), "rwd");

                                          //1.设置本地文件大小跟服务器的文件大小一致

                                          file.setLength(len);

                                          //设置进度条的最大值

                                          pb.setMax(len);

                                          //2 .假设开启3 个线程

                                          intthreadnumber = 3;

                                          intblocksize = len / threadnumber;

                     *线程1 0~blocksize 线程21*bolocksize ~ 2*blocksize 线程3

                      * 2*blocksize ~ 文件末尾

                                          for(int i = 0; i < threadnumber; i++) {

                                                 intstartposition = i * blocksize;

                                                 intendpositon = (i + 1) * blocksize;

                                                 if(i == (threadnumber - 1)) {

                                                        //最后一个线程

                                                        endpositon= len;

                                                 }

                                                 DownLoadTasktask = new DownLoadTask(i, path,

                                                               startposition,endpositon);

                                                 task.start();}

在网络访问的时候有一个Range参数书数据中下载的开始和结束位置,利用这个参数可以设置数据的多线程下载数据。

conn.setRequestProperty("Range","bytes="+startposition + "-"+ endpositon);

2)断点下载

断点下载需要记录当前已下载的进度。这就需要一个文件记录已下载的进度。

File postionfile = newFile("/mnt/sdcard/" + threadid + ".txt");

                            URLurl = new URL(filepath);

                            HttpURLConnectionconn = (HttpURLConnection) url

                                          .openConnection();

                            System.out.println("线程" + threadid + "正在下载 " + "开始位置 : "

                                          +startposition + "结束位置 " + endpositon);

 

                            if(postionfile.exists()) {

                                   FileInputStreamfis = new FileInputStream(postionfile);

                                   byte[]result = StreamTool.getBytes(fis);

                                   Stringstr = new String(result);

                                   if(!"".equals(str)) {

                                          intnewstartposition = Integer.parseInt(str);

                                          if(newstartposition > startposition) {

                                                 startposition= newstartposition;

                                          }}}

                            //"Range", "bytes=2097152-4194303")

                            conn.setRequestProperty("Range","bytes=" + startposition + "-"

                                          +endpositon);

                            conn.setRequestMethod("GET");

                            conn.setConnectTimeout(5000);

                            conn.setRequestProperty("User-Agent",

                                          "Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1; SV1)");

                            InputStreamis = conn.getInputStream();

                            RandomAccessFilefile = new RandomAccessFile("/mnt/sdcard/"

                                          +getFilenName(filepath), "rwd");

                            //设置 数据从文件哪个位置开始写

                            file.seek(startposition);

                            byte[]buffer = new byte[1024];

                            intlen = 0;

                            //代表当前读到的服务器数据的位置 ,同时这个值已经存储的文件的位置

                            intcurrentPostion = startposition;

                            //创建一个文件对象 ,记录当前某个文件的下载位置

                            while((len = is.read(buffer)) != -1) {

                                   if(stopflag) {

                                          return;

                                   }

                                   file.write(buffer,0, len);

                                   synchronized(DemoActivity.this) {

                                          total+= len;

                                   }

                                   currentPostion+= len;

                                   //需要把currentPostion信息给持久化到存储设备

                                   Stringposition = currentPostion + "";

                                   FileOutputStream fos = newFileOutputStream(postionfile);

                                   fos.write(position.getBytes());

                                   fos.flush();

                                   fos.close();

                            }

                            file.close();

                            System.out.println("线程" + threadid + "下载完毕");

                            //当线程下载完毕后 把文件删除掉

                            if(postionfile.exists()) {

                                   postionfile.delete();

2、进度条设置

prosgressBar:进度条

有两个属性:max  设进度条范围值

Progerss: 单签进度

主界面的更改只能由主线程控制,但是需要的数据又在子线程里所以有必要通过一定的消息机制去处理种情况,这就是安卓中的消息处理机制Hanlder。

Hanlder:必须在主线程创建

在主线程中中穿件Handler,重写其中的handleMessage方法,来进行获取数据和控制主线程的操作

private Handler handler = new Handler() {

              publicvoid handleMessage(Message msg) {

                     pb.setProgress(total);

                     intmax = pb.getMax();

                     if(total >= (max - 1)) {

                            total= max;

                            flag= false;}

                     intresult = total * 100 / max;

                     tv.setText("当前进度 :" + result +"%");

 

                     super.handleMessage(msg);

              }

需要注意的是需要在子线程中有对应的提供数据的操作

new Thread() {

                                   publicvoid run() {

                                          super.run();

                                          while(flag) {

                                                 try{

                                                        sleep(1000);

                                                        //如果total > =文件长度

                                                        Messagemsg = new Message();

                                                        handler.sendMessage(msg);

                                                 }catch (InterruptedException e) {

                                                        e.printStackTrace();

                                                 }}}}.start();

3、ANR异常

Anr异常是指由于主线程等待过久引起的程序异常。

对于这种情况就需要将耗时的操作放在子线程中进行。

4、意图操作(Intent)

intent 意图 , 描述一个动作, 激活一个组件

1)两种意图

显示意图:显示意图的操作都必须要知道被激活的组件的包名和 class的名字

  /* 第一种写法

    * Intent intent = new Intent();

           intent.setClassName("cn.itcast.mutileactivity","cn.itcast.mutileactivity.Demo2Activity");*/

    // 第二种写法

    //   Intent intent = newIntent(this,Demo2Activity.class);

       /*

        *第三种写法

           Intent intent = new Intent();

           ComponentName  component = newComponentName("cn.itcast.mutileactivity","cn.itcast.mutileactivity.Demo2Activity");

           intent.setComponent(component);

        */

隐式意图

隐式意图需要在清单文件中配置相关的操作属性,主要的有action节点和cateary节点,这两个节点都要在对应的activity节点下配置。

另外还有一个data节点,这个节点有三个属性:scheme属性,用来设置路径的前缀;host属性,用来设置主机名;mineType属性,用来设置数据类型;

 

Intent intent = new Intent();

//        intent.setAction("cn.itcast.mutileactivity.xxx");

//        intent.addCategory("android.xxx");

//        intent.setData(Uri.parse("itcast://cn.itcast.demo"));

           //intent.setType(type);  // mime 数据类型 image/jpeg

在系统中也可以利用这种方式直接调用手机系统的其他界面

示例:调用图片界面

Intent intent =new Intent();

intent.setAction(Intent.ACTION_PICK);

intent.setType("image/jpeg");

2)使用意图传递数据

在不同的界面之间可能需要在转入一个界面的时候调用到另一个界面操作时候的数据,这样就有了使用意图传递数据的方法。

其实就是在激活另一个界面的调用(startActivity方法之前)时候使用putExtras的方法将需要传递的数据放在这个方法中进行传递。

public void click(View view){

           EditText et = (EditText)this.findViewById(R.id.et_activity01);

           String content =et.getText().toString().trim();

           Intent intent = newIntent(this,Demo2Activity.class);

           //intent.putExtra("cn.itcast.passdata.name", content);

           //基本数据类型和基本数据类型的数组 我们都可以通过intent传递

           Bundle bundle = new Bundle();

           bundle.putString("cn.itcast.passdata.name",content);

           intent.putExtras(bundle);

           startActivity(intent);}}

同时在需要接受数据的界面中设置一个接受数据的方法getExtras

public void onCreate(BundlesavedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.main2);

       //获取到激活他的意图

       Intent intent = getIntent();

      // String name =intent.getStringExtra("cn.itcast.passdata.name");

        Bundle bundle = intent.getExtras();

        String name = bundle.getString("cn.itcast.passdata.name");

        TextView tv  =(TextView)this.findViewById(R.id.tv_activity02);

        tv.setText("你好 :"+name); }

3)获取返回值的数据

界面一种要设置startActivityForResult的方式激活界面2,要注意的是必须在界面2中激活界面一,激活的方法

Intent data =new Intent();

                            data.putExtra("name",name);

                            setResult(3,data);相当于激活了界面一,但是不需要指向界面一。 0

界面一种的操作

public class DemoActivity extends Activity{

       EditTextet, et2;

       publicvoid onCreate(Bundle savedInstanceState) {

              super.onCreate(savedInstanceState);

              setContentView(R.layout.main);

              et= (EditText) this.findViewById(R.id.et_contact1);

              et2= (EditText) this.findViewById(R.id.et_contact2);

       }

       publicvoid click(View view) {

              Intentintent = new Intent(this, ContactActivity.class);

              //startActivity(intent);

              startActivityForResult(intent,1);}

       publicvoid click2(View view) {

              Intentintent = new Intent(this, ContactActivity.class);

              //startActivity(intent);

              startActivityForResult(intent,2);}

        * 当被激活的activity 使用完毕 销毁的时候 就会执行onActivityresult的方法@Override

       protectedvoid onActivityResult(int requestCode, int resultCode, Intent data) {

              System.out.println("结果码为"+ resultCode);

              super.onActivityResult(requestCode,resultCode, data);

 

              if(data != null) {

                     Stringname = data.getStringExtra("name");

                     if(requestCode == 1) {

                            et.setText(name);

                     }elseif(requestCode == 2){

                            et2.setText(name);}}}

5、Activity的生命周期

Anctivity声生命周期图

6、应用异常关闭处理

应用异常结束时候的处理:异常的时候保存数据,

 /**

    * 在activity被异常 回收的时候 会被执行

    */

       protectedvoid onSaveInstanceState(Bundle outState) {

              super.onSaveInstanceState(outState);

              outState.putInt("page",30);}

在创建actibvity的时候可以操作异常数据。

 if(savedInstanceState!=null){

              page =savedInstanceState.getInt("page");

              System.out.println("定位到 第 "+ page+"页");

       }


0 0
原创粉丝点击