zoukankan      html  css  js  c++  java
  • 反射机制及开源框架xUitls的使用,使用HttpUtils通过断点续传下载文件

    反射:

    Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法

    对于任意一个对象,都能够调用它的任意一个方法和属性

    Java反射机制主要提供下面几种用途:

    1•在运行时判断任意一个对象所属的类

    2•在运行时构造任意一个类的对象

    3•在运行时判断任意一个类所具有的成员变量和方法

    4•在运行时调用任意一个对象的方法

    第一步 得到某个类的class对象,有三种方式;

    方式一:  Class<Student> class1 = Student.class;

    方式二:  Class class2 = Class.forName("包名");

    方式三:  Student student = new Student();
           Class class3 = student.getClass();

    然后我们就可以对类中的方法属性进行操作了..

    访问类中的属性了,属性包括了私有公有的属性

                Field fields[] = class1.getDeclaredFields();
                for (Field field : fields) {
                    System.out.println(field);
                }

    通过反射创建对象

          //1.得到无参构造方法
                Constructor<Student> constructor = class1.getConstructor();
                //2.创建对象
                Student stu = constructor.newInstance();
                //等价于Student stu = new Student();

    调用set方法设置数据

                Method method = class1.getDeclaredMethod("setName", new Class[]{String.class});
                //私有方法需要设置权限
                method.setAccessible(true);
                //2.通过之前的student对象调用setName表示的方法
                method.invoke(stu, new Object[]{"张三"});

    通过Get方法得到数据

    Method getName = class1.getDeclaredMethod("getName", new Class[]{});
                //通过之前的student对象调用getName表示的方法
                Object object = getName.invoke(stu, new Object[]{});
                System.out.println(object);

    第三方框架XUitls的使用:
      下载XUils   地址:https://github.com/wyouflf/xUtils

      导入项目,将jar包复制到当前工程下的libs目录下---点击该jar包-右键--As a Library --ok

    • xUtils 包含了很多实用的android工具。
    • xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响...
    • xUitls 最低兼容android 2.2 (api level 8)

    目前xUtils主要有四大模块:

    • DbUtils模块:

      • android中的orm框架,一行代码就可以进行增删改查;
      • 支持事务,默认关闭;
      • 可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名);
      • 支持绑定外键,保存实体时外键关联实体自动保存或更新;
      • 自动加载外键关联实体,支持延时加载;
      • 支持链式表达查询,更直观的查询语义,参考下面的介绍或sample中的例子。
    • ViewUtils模块:

      • android中的ioc框架,完全注解方式就可以进行UI,资源和事件绑定;
      • 新的事件绑定方式,使用混淆工具混淆后仍可正常工作;
      • 目前支持常用的20种事件绑定,参见ViewCommonEventListener类和包com.lidroid.xutils.view.annotation.event。
    • HttpUtils模块:

      • 支持同步,异步方式的请求;
      • 支持大文件上传,上传大文件不会oom;
      • 支持GET,POST,PUT,MOVE,COPY,DELETE,HEAD,OPTIONS,TRACE,CONNECT请求;
      • 下载支持301/302重定向,支持设置是否根据Content-Disposition重命名下载的文件;
      • 返回文本内容的请求(默认只启用了GET请求)支持缓存,可设置默认过期时间和针对当前请求的过期时间。
    • BitmapUtils模块:

      • 加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象;
      • 支持加载网络图片和本地图片;
      • 内存管理使用lru算法,更好的管理bitmap内存;
      • 可配置线程加载线程数量,缓存大小,缓存路径,加载显示动画等...
      • 使用xUtils快速开发框架需要有以下权限:

        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    ViewUtils使用方法 

    API:http://xutilsapi.oschina.mopaas.com/

    • 完全注解方式就可以进行UI绑定和事件绑定。
    • 无需findViewById和setClickListener等。

    注解:从原理上讲,注解处理器就是通过反射机制获取被检查方法上的注解信息,然后根据注解元素的值进行特定的处理。

    首先需要在activity中注入:(否则控件,资源,,注入没用)

    //在Activity中注入:
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ViewUtils.inject(this); //注入view和事件
        ...
        textView.setText("some text...");
    注入布局:相当于setContentView(R.layout.activity_main);
    @ContentView(R.layout.activity_main)
    public class MainActivity extends AppCompatActivity {

      注入控件 等价于 findVIewById(R.id.tv_text)

        @ViewInject(R.id.tv_text)
        private TextView tvText;
    注入数据资源
    //id表示资源的id type表示资源的数据类型,String,demens.color,drawable,animation...
        @ResInject(id = R.string.hello,type = ResType.String)
        private String hello;

    注入点击事件:方法名可以任意,但是参数必须与原始的参数一致

    // 取消了之前使用方法名绑定事件的方式,使用id绑定不受混淆影响,方法名可以自定义
    // 支持绑定多个id @OnClick({R.id.id1, R.id.id2, R.id.id3})
    // or @OnClick(value={R.id.id1, R.id.id2, R.id.id3}, parentId={R.id.pid1, R.id.pid2, R.id.pid3})

        @OnClick(R.id.btn01)
        public void onButtonClick(View view){
            Toast.makeText(this,"点击了btn01",Toast.LENGTH_SHORT).show();
    
        }

    !!!使用碎片可以进行碎片注入,注入碎片后方可对其中的控件进行注入操作

    在Fragment中注入:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.bitmap_fragment, container, false); // 加载fragment布局
        ViewUtils.inject(this, view); //注入view和事件
        ...
    }

    BitmapUtils使用方法

     首先我们需要创建一个BitmapUtils对象,一个活动只需要创建一个,因此我们设置在MyApplication中,注意需要在清单文件中注册

    public class MyApplication extends Application {
        private static BitmapUtils bitmapUtils;
        @Override
        public void onCreate() {
            super.onCreate();
            //创建对象
           bitmapUtils = new BitmapUtils(getApplicationContext());
        }
        public static BitmapUtils getBitmapUtils(){
            return bitmapUtils;
        }
    }

    这里将该对象进行了封装,活动只需要调用MyApplication的getBitmapUtils方法就可以得到该对象了,主活动的onCreate方法中注入actiivity和得到bitmapUtils对象

            ViewUtils.inject(this);//注入view和事件
           bitmapUtils = MyApplication.getBitmapUtils();

    加载本地图片(路径以/开头, 绝对路径):需要加入权限(android.permission.WRITE_EXTERNAL_STORAGE)

      
        @OnClick(R.id.btn_file)
        public void onClickSDCard(View view){
            //参数一:要设置图片的图片控件
            bitmapUtils.display(image,"/mnt/sdcard/img/a.jpg");
    加载assets中的图片(路径以assets开头)
        @OnClick(R.id.btn_assert)
        public void onClickAssets(View view){
            bitmapUtils.display(image,"assets/a.jpg");
        }

    加载网络图片:(需要加入权限android.permission.INTERNET)

    显示图片到指定控件,如果是ImageView,会调用setImageBitmap(bitmap);其他控件使用setBackgroundDrawable(drawable)
    方式一:

    container - 控件View
    uri - 本地文件完整路径,assets文件路径(assets/xxx),或者URL地址

    itmapUtils.display(image,"http://p1.so.qhmsg.com/t01e63fec232667f916.jpg");

    方式二:

      参数:
    container - 控件View
    uri - 本地文件完整路径,assets文件路径(assets/xxx),或者URL地址
    displayConfig - 图片显示配置项BitmapDisplayConfig

    BitmapDisplayConfig bitmapDisplayConfig = new BitmapDisplayConfig();//创建图片显示配置项对象 //设置最大尺寸 bitmapDisplayConfig.setBitmapMaxSize(new BitmapSize(200,200)); //设置动画 ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); scaleAnimation.setDuration(2000); scaleAnimation.setRepeatCount(1); scaleAnimation.setFillAfter(true); bitmapDisplayConfig.setAnimation(scaleAnimation); // bitmapUtils.display(image,"http://p1.so.qhmsg.com/t01e63fec232667f916.jpg",bitmapDisplayConfig);

    方式三:

        //该方法设置动画效果没用
     参数:
    container - 控件View
    uri - 本地文件完整路径,assets文件路径(assets/xxx),或者URL地址
    callBack - 图片加载回调接口BitmapLoadCallBack*/

    bitmapUtils.display(image, "http://p1.so.qhmsg.com/t01e63fec232667f916.jpg", new BitmapLoadCallBack<ImageView>() { //加载图片回调监听 @Override public void onLoadCompleted(ImageView imageView, String s, Bitmap bitmap, BitmapDisplayConfig bitmapDisplayConfig, BitmapLoadFrom bitmapLoadFrom) { //设置回调后的图片 imageView.setImageBitmap(bitmap); } //加载失败 @Override public void onLoadFailed(ImageView imageView, String s, Drawable drawable) { } });

    方式四:

     //该方法设置动画效果没用

      参数:container - 控件View

        uri - 本地文件完整路径,assets文件路径(assets/xxx),或者URL地址

      displayConfig - 图片显示配置项BitmapDisplayConfig

     callBack - 图片加载回调接口BitmapLoadCallBack

    bitmapUtils.display(image, "http://p1.so.qhmsg.com/t01e63fec232667f916.jpg", bitmapDisplayConfig, new BitmapLoadCallBack<ImageView>() { @Override public void onLoadCompleted(ImageView imageView, String s, Bitmap bitmap, BitmapDisplayConfig bitmapDisplayConfig, BitmapLoadFrom bitmapLoadFrom) { imageView.setImageBitmap(bitmap); } @Override public void onLoadFailed(ImageView imageView, String s, Drawable drawable) { } });

    DBUtils使用方法

    创建数据库:

      参数:
    context - android.content.Context
    dbDir - 数据库文件存储路径
    dbName - 数据库文件名
    dbVersion - 数据库版本号
    dbUpgradeListener - 数据库版本升级通知接口
    返回:
    DbUtils实例DbUtils

    dbUtils = DbUtils.create(this, getCacheDir().getAbsolutePath(), "dbUtils.db",1, this)

    这里由于该类实现了DbUtils.DbUpgradeListener,实现了其中的方法,所以最后一个参数传入this

    实现的方法

     /**
         * 更新数据库
         * @param dbUtils
         * @param i 旧版本
         * @param i1 新版本
         */
        @Override
        public void onUpgrade(DbUtils dbUtils, int i, int i1) {
            Log.i("tag","onUpgrade--i--"+i+"--i1--"+i1);
            dbUtils = DbUtils.create(this, getCacheDir().getAbsolutePath(), "dbUtils.db",2, this);
        }

    创建表:

     * 创建表
         * @param v
         */
        @OnClick(R.id.btn_createTab)
        public void onCreateTable(View v){
    
            //创建数据库表,当表不存在时
            //entityType - 实体类类型Class
            try {
                dbUtils.createTableIfNotExist(Student.class);

    简单的增删改查方法:

    增:

    保存实体到DB(insert)
    根据实体类注解,自动创建表;
    只持久化基本数据类型、java.lang.*等,不能处理的类型自动忽略;
    对静态属性、添加忽略注解属性自动忽略。
    插入一条数据:
        Student student = new Student();
                student.setAge(19);
                student.setName("张三");
                student.setSex("男");
                //插入一条数据
                dbUtils.save(student);

    插入多条数据:

                //插入多条数据,当有一条数据出错时,后面的数据不会再进行插入操作
                List<Student>dataList = new ArrayList<>();
                for (int i = 0; i < 20; i++) {
                    Student student = new Student();
                    student.setName("alice"+(i+1));
                    student.setAge((i+19));
                    if(i % 2 == 0) {
                        student.setSex("男");
                    }else{
                        student.setSex("女");
                    }
                    dataList.add(student);
                }
                dbUtils.saveAll(dataList);

    删:

         //删除id>85,age>22的数据
                dbUtils.delete(Student.class,WhereBuilder.b("_id",">","85").and("age",">","22"));

    改:

                //更新_id>40的数据为贝塔,1000,女
                List<Student> list =  dbUtils.findAll(Selector.from(Student.class).where(WhereBuilder.b("_id",">","40")));
                for (int i = 0; i < list.size(); i++) {
                    Student s = list.get(i);
                    s.setAge(1000);  s.setName("贝塔");  s.setSex("女");
                    // updateColumnNames为空时,更新所有字段的值
                    //entity - 实体类实例  updateColumnNames -String..可变参数 需要更新的字段名,
              dbUtils.update(s,"age","name","sex");

        //更新所有_id<10的名字
        dbUtils.update(s,WhereBuilder.b("_id","<","10"),"name");
     

    查:

          //查询所有数据
             List<Student> list = dbUtils.findAll(Student.class);

      //查询1
    List<DbModel> dbModelAll = dbUtils.findDbModelAll(DbModelSelector.
    from(Student.class). //表示从那个表查询
    select("_id", "name", "sex", "age"). //表示查询的字段
    where("age", "<", "22")); //表示查询条件*/
      //查询所有_id<10的数据
    // List<Student> list = dbUtils.findAll(Selector.from(Student.class).where("_id", "<", "10"));

     实体类:

    /**
     * 创建表
     *
     */
    //指定表名
    @Table(name = "Student")
    public class Student {
        //指定列名
        @Column(column = "_id")
        //指定是主键
        @Id(column = "_id")
        private int _id;
    
        @Column(column = "name")
        private String name;
    
        @Column(column = "age")
        //限制条件 年龄大于18
        @Check("age > 18 ")
        private int age;
    
        //性别必须为男或者女
        @Column(column = "sex")
        @Check("sex in ('男','女')")
        private String sex;
        public int get_id() {
            return _id;
        }
        public void set_id(int _id) {
            this._id = _id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
    }

    HttpUtils使用

    httpUtils仅仅支持安卓6.0以下应用,因为里面使用的都是HttpClient的网络请求方式,而google公司已经将其弃用.

    普通Get方法:

       //声名httputils工具
            HttpUtils httpUtils = new HttpUtils();
            //发送请求
           httpUtils.send(HttpRequest.HttpMethod.GET, pathGet, new RequestCallBack<String>() {
                //*请求成功的回调*//*
                @Override
                public void onSuccess(ResponseInfo<String> responseInfo) {
                    //获取数据
                    String string  = responseInfo.result;
                    Log.i("AAA",string);
                    Log.i("AAA","ThreadName:-" + Thread.currentThread().getName() + "-threadId-" + Thread.currentThread().getId());
                }
                @Override
                public void onFailure(HttpException e, String s) {
                }
            });
        }

    post方法:

       HttpUtils httpUtils = new HttpUtils();
            //post提交的字段:pageNo=1&pageSize=20&serialIds=2143,3404&v=4.0.0
            //  String pathPost = "http://mrobot.pcauto.com.cn/v2/cms/channels/1?";
            RequestParams requestParams = new RequestParams();
            //设置post请求参数
            requestParams.addBodyParameter("pageNo", "1");
            requestParams.addBodyParameter("pageSize", "20");
            requestParams.addBodyParameter("serialIds", "2143,3404");
            requestParams.addBodyParameter("v", "4.0.0");
    
         /*   com.lidroid.xutils.http.client.HttpRequest.HttpMethod method,  请求类型  Get,Post..
            @NotNull java.lang.String url,  网络地址
            com.lidroid.xutils.http.RequestParams params,  请求参数
            com.lidroid.xutils.http.callback.RequestCallBack<T> callBack  请求成功的回调
            httpUtils.send()*/
            httpUtils.send(HttpRequest.HttpMethod.POST, pathPost, requestParams, new RequestCallBack<String>() {
                @Override
                public void onSuccess(ResponseInfo<String> responseInfo) {
                    Log.i("AAA", "onSuccess: " + responseInfo.result);
                }
    
                @Override
                public void onFailure(HttpException e, String s) {
                }
            });
        }



    • 使用HttpUtils下载文件:(需加入网络权限,写入sd卡的权限)

    • 支持断点续传,随时停止下载任务,开始任务
    • 注意:回调的方法在主线程中执行
    @ContentView(R.layout.activity_main)
    public class MainActivity extends Activity {
        @ViewInject(R.id.tvText)
        private TextView tvText;
        private String pathApk = "http://down.72g.com/upload/app/201407/201407150923238621.apk";
        private ProgressDialog progressDialog;
        private HttpHandler<File> httpHandler;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //注入activity
            ViewUtils.inject(this);
            //初始化对话框
            initProgressDialog();
            
        }
        /*初始化对话框*/
        private void initProgressDialog() {
            //创建进度条对话框
             progressDialog = new ProgressDialog(this);
             //设置标题
             progressDialog.setTitle("下载文件");
             //设置信息
             progressDialog.setMessage("玩命下载中...");
             //设置显示的格式
             progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            //设置按钮
             progressDialog.setButton(ProgressDialog.BUTTON_NEGATIVE, "暂停",new DialogInterface.OnClickListener(){
    
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //点击取消正在下载的操作,再次触发点击事件时,会重新创建httpHandler对象,但会从暂停的地方继续下载,从而实现了断点续传的操作
                    httpHandler.cancel();
        
                }});
        }
        @OnClick(R.id.btn_download)
        public void onClickDownLoadFile(View view){
            //声明httpUtils工具
            HttpUtils httpUtils = new HttpUtils();
            //存储的路径
             String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/app3.apk";
        //下载 httpHandler
    = httpUtils.download(pathApk,//文件地址
                path,//文件下载的目标目录
                true,// 如果目标文件存在,接着未完成的部分继续下载。服务器不支持RANGE时将从新下载。
               true,// 如果从请求返回信息中获取到文件名,下载完成后自动重命名
        new RequestCallBack<File>() {//下载的回调,在主线程中运行
      /*执行下载操作之前调用*/
                 @Override
                public void onStart() {
                    super.onStart();
                    //显示对话框
                    progressDialog.show();
                }
                 /*正在下载的时候调用*/
                 @Override
                public void onLoading(long total, long current, boolean isUploading) {
                    super.onLoading(total, current, isUploading);
                //    Log.i("tag", "线程--"+Thread.currentThread().getName());
    //                Log.i("tag", "current--total--"+current+"--"+total);
                    //设置进度
                    progressDialog.setProgress((int)(current*100/total));
                }
                /*请求成功的时候调用*/
                @Override
                public void onSuccess(ResponseInfo<File> responseInfo) {
                    progressDialog.dismiss();
                    Log.i("tag","下载成功");
                    //获得下载后的文件
                    File file = responseInfo.result;
                    InstallApkUtils.inStallApk(MainActivity.this, file);
                }
                /*请求失败的时候调用*/
                @Override
                public void onFailure(HttpException error, String msg) {
                    Log.i("tag", "下载失败");
                    progressDialog.dismiss();
                }
                /*取消的时候调用*/
                @Override
                public void onCancelled() {
                    super.onCancelled();
                    Log.i("tag","取消下载");
                }
            }); 
            
        }
        
    }

    安装apk的工具类:

    public static void inStallApk(Context context,File file){
            Intent intent = new Intent();
            //隐式意图激活安装 apk 的activity
            intent.setAction(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
            context.startActivity(intent);
        }

    效果:

  • 相关阅读:
    使用Intent传递类对象
    C#中关于类的序列化
    Android 中使用内存监测工具Heap,及内存分析工具 MAT
    Android Framework 记录之一
    Android 2.3发短信详细流程
    AIDL原理解析
    eclipse 快捷键
    什么时候加上android.intent.category.DEFAULT和LAUNCHER
    Monkey测试简介
    Phone状态的监听机制
  • 原文地址:https://www.cnblogs.com/fangg/p/5915839.html
Copyright © 2011-2022 走看看