Tears_fg

导航

反射机制及开源框架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);
    }

效果:

 

posted on 2016-09-28 12:04  Tears_fg  阅读(498)  评论(0编辑  收藏  举报