Android流行框架菜鸟式 | 实践

本文深入讲解了Android开发中常用的框架,包括EventBus的组件间通讯、Retrofit的网络请求、Butterknife的代码模板生成、GreenDao的数据库操作、Glide的图片加载以及RxAndroid的异步处理,为开发者提供了全面的框架应用指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android流行框架菜鸟式实践

扩展需自己过多的学习

Evenbus (事件总线-组件间通讯)

依赖

implementation 'org.greenrobot:eventbus:3.2.0'

作用

简化组件间的通信

替换一下handle,intent,broadcast的使用

三要素

  • Event事件 任意类型
  • Subscribe事件订阅 在事件方法上使用Subscribe注解并指定线程模型
  • Publisher事件发布者 任意线程发布一般使用Eventbus.getdefault().post(object)

四种线程模型

  • posting 事件处理和事件发布在同一个线程
  • main 事件处理在ui线程
  • backgroup 事件处理后台线程 若事件发布在main线程,则会创建一个后台线程;若事件发布本身在后台线程,事件处理不许再创建后台线程,在当前线程执行
  • async 始终创建一个子线程来执行事件处理

使用步骤

  • 定义事件类

    传输数据的Bean

    public class MessageEvent{}
    
  • 注册事件

    在Activity oncreate方法里面

    EventBus.getDefault().register(this);

  • 解除事件

    在Activity ondestroy方法里面

    EventBus.getDefault().unregister(this);

  • 发送事件

    EventBus.getDefault().post(new OneMessage("这是啥玩意"));

  • 处理事件

     @Subscribe(threadMode = ThreadMode.MAIN)
        public void eventPost(OneMessage oneMessage){
            textView.setText(oneMessage.getMessage());
        }
    

注意: 每一个Activity需要注册Evenbus之后才能处理执行事件方法,不注册可以发送事件

Retrofit (网络请求)

作用

网络请求框架的封装,基于okhttp [请求内部使用okhttp,retrofit是对请求接口的封装]

  • 使用注解配置网络请求参数
  • 同步 & 异步 请求
  • 支持RxJava
  • 多格式数据解析

使用

  • 创建Java Bean [服务器返回的数据]

    public class Github {
    
        private String login;
        private long id;
        private String node_id;
        private String avatar_url;
        private String gravatar_id;
        private String url;
        private String html_url;
        private String followers_url;
        private String following_url;
        private String gists_url;
        private String starred_url;
        private String subscriptions_url;
        private String organizations_url;
        private String repos_url;
        private String events_url;
        private String received_events_url;
        private String type;
        private boolean site_admin;
        private String name;
        private String company;
        private String blog;
        private String location;
        private String email;
        private String hireable;
        private String bio;
        private int public_repos;
        private int public_gists;
        private int followers;
        private int following;
        private Date created_at;
        private Date updated_at;
        public void setLogin(String login) {
            this.login = login;
        }
        public String getLogin() {
            return login;
        }
    
        public void setId(long id) {
            this.id = id;
        }
        public long getId() {
            return id;
        }
    
        public void setNode_id(String node_id) {
            this.node_id = node_id;
        }
        public String getNode_id() {
            return node_id;
        }
    
        public void setAvatar_url(String avatar_url) {
            this.avatar_url = avatar_url;
        }
        public String getAvatar_url() {
            return avatar_url;
        }
    
        public void setGravatar_id(String gravatar_id) {
            this.gravatar_id = gravatar_id;
        }
        public String getGravatar_id() {
            return gravatar_id;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
        public String getUrl() {
            return url;
        }
    
        public void setHtml_url(String html_url) {
            this.html_url = html_url;
        }
        public String getHtml_url() {
            return html_url;
        }
    
        public void setFollowers_url(String followers_url) {
            this.followers_url = followers_url;
        }
        public String getFollowers_url() {
            return followers_url;
        }
    
        public void setFollowing_url(String following_url) {
            this.following_url = following_url;
        }
        public String getFollowing_url() {
            return following_url;
        }
    
        public void setGists_url(String gists_url) {
            this.gists_url = gists_url;
        }
        public String getGists_url() {
            return gists_url;
        }
    
        public void setStarred_url(String starred_url) {
            this.starred_url = starred_url;
        }
        public String getStarred_url() {
            return starred_url;
        }
    
        public void setSubscriptions_url(String subscriptions_url) {
            this.subscriptions_url = subscriptions_url;
        }
        public String getSubscriptions_url() {
            return subscriptions_url;
        }
    
        public void setOrganizations_url(String organizations_url) {
            this.organizations_url = organizations_url;
        }
        public String getOrganizations_url() {
            return organizations_url;
        }
    
        public void setRepos_url(String repos_url) {
            this.repos_url = repos_url;
        }
        public String getRepos_url() {
            return repos_url;
        }
    
        public void setEvents_url(String events_url) {
            this.events_url = events_url;
        }
        public String getEvents_url() {
            return events_url;
        }
    
        public void setReceived_events_url(String received_events_url) {
            this.received_events_url = received_events_url;
        }
        public String getReceived_events_url() {
            return received_events_url;
        }
    
        public void setType(String type) {
            this.type = type;
        }
        public String getType() {
            return type;
        }
    
        public void setSite_admin(boolean site_admin) {
            this.site_admin = site_admin;
        }
        public boolean getSite_admin() {
            return site_admin;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
    
        public void setCompany(String company) {
            this.company = company;
        }
        public String getCompany() {
            return company;
        }
    
        public void setBlog(String blog) {
            this.blog = blog;
        }
        public String getBlog() {
            return blog;
        }
    
        public void setLocation(String location) {
            this.location = location;
        }
        public String getLocation() {
            return location;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
        public String getEmail() {
            return email;
        }
    
        public void setHireable(String hireable) {
            this.hireable = hireable;
        }
        public String getHireable() {
            return hireable;
        }
    
        public void setBio(String bio) {
            this.bio = bio;
        }
        public String getBio() {
            return bio;
        }
    
        public void setPublic_repos(int public_repos) {
            this.public_repos = public_repos;
        }
        public int getPublic_repos() {
            return public_repos;
        }
    
        public void setPublic_gists(int public_gists) {
            this.public_gists = public_gists;
        }
        public int getPublic_gists() {
            return public_gists;
        }
    
        public void setFollowers(int followers) {
            this.followers = followers;
        }
        public int getFollowers() {
            return followers;
        }
    
        public void setFollowing(int following) {
            this.following = following;
        }
        public int getFollowing() {
            return following;
        }
    
        public void setCreated_at(Date created_at) {
            this.created_at = created_at;
        }
        public Date getCreated_at() {
            return created_at;
        }
    
        public void setUpdated_at(Date updated_at) {
            this.updated_at = updated_at;
        }
        public Date getUpdated_at() {
            return updated_at;
        }
    
        @Override
        public String toString() {
            return "Github{" +
                    "login='" + login + '\'' +
                    ", id=" + id +
                    ", node_id='" + node_id + '\'' +
                    ", avatar_url='" + avatar_url + '\'' +
                    ", gravatar_id='" + gravatar_id + '\'' +
                    ", url='" + url + '\'' +
                    ", html_url='" + html_url + '\'' +
                    ", followers_url='" + followers_url + '\'' +
                    ", following_url='" + following_url + '\'' +
                    ", gists_url='" + gists_url + '\'' +
                    ", starred_url='" + starred_url + '\'' +
                    ", subscriptions_url='" + subscriptions_url + '\'' +
                    ", organizations_url='" + organizations_url + '\'' +
                    ", repos_url='" + repos_url + '\'' +
                    ", events_url='" + events_url + '\'' +
                    ", received_events_url='" + received_events_url + '\'' +
                    ", type='" + type + '\'' +
                    ", site_admin=" + site_admin +
                    ", name='" + name + '\'' +
                    ", company='" + company + '\'' +
                    ", blog='" + blog + '\'' +
                    ", location='" + location + '\'' +
                    ", email='" + email + '\'' +
                    ", hireable='" + hireable + '\'' +
                    ", bio='" + bio + '\'' +
                    ", public_repos=" + public_repos +
                    ", public_gists=" + public_gists +
                    ", followers=" + followers +
                    ", following=" + following +
                    ", created_at=" + created_at +
                    ", updated_at=" + updated_at +
                    '}';
        }
    }
    
    
  • 创建网络请求接口

    public interface GitHubService {
        @GET("users/Primer1889")
        Call<Github> listRepos();
    }
    
  • 创建Retrofit实例

     retrofit = new Retrofit.Builder()
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl("https://api.github.com/")
                    .build();
    
  • 创建网络接口实例 & 配置请求参数

     GitHubService service = retrofit.create(GitHubService.class);
    
                Call<Github> repos = service.listRepos();
    
    
  • 发送请求

    retrofit请求需要在子线程里面进行,handler满足需求,Evenbus也满足需求,当然也有其他方式,这里主要使用最简单的handle和高效的Evenbus

    方式一 : 在handle里面

    private Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
    
                GitHubService service = retrofit.create(GitHubService.class);
    
                Call<Github> repos = service.listRepos();
    
                repos.enqueue(new retrofit2.Callback<Github>() {
                    @Override
                    public void onResponse(Call<Github> call, Response<Github> response) {
                        Log.d(TAG, "onResponse: 响应结果");
                        Log.d(TAG, "onResponse: 姓名"+response.body().getName());
                        Log.d(TAG, "onResponse: \n"+response.body().toString());
    
                    }
    
                    @Override
                    public void onFailure(Call<Github> call, Throwable t) {
                        Log.d(TAG, "onFailure: 响应失败"+t.toString());
                    }
                });
            }
        };
    

    方式二: Evenbus

     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_translate);
            EventBus.getDefault().register(this);
    
            //http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello
            retrofit = new Retrofit.Builder()
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl("https://api.github.com/")
                    .build();
    
            service = retrofit.create(GitHubService.class);
    
    
            EventBus.getDefault().post(new GithubMessage("Primer1889"));
            //handler.sendMessage(new Message());
    
            Log.d(TAG, "onCreate: 结束");
        }
    
    
     @Subscribe(threadMode = ThreadMode.ASYNC)
        public void getGithubNameMsg(GithubMessage githubMessage){
    
            Call<Github> repos = service.listRepos();
    
            repos.enqueue(new retrofit2.Callback<Github>() {
                @Override
                public void onResponse(Call<Github> call, Response<Github> response) {
                    Log.d(TAG, "onResponse: 响应结果");
                    Log.d(TAG, "onResponse: 姓名"+response.body().getName());
                    Log.d(TAG, "onResponse: \n"+response.body().toString());
    
                }
    
                @Override
                public void onFailure(Call<Github> call, Throwable t) {
                    Log.d(TAG, "onFailure: 响应失败"+t.toString());
                }
            });
        }
    

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ASyxUpm8-1583033887636)(C:\Users\Primer4\Documents\学习笔记\1582896312476.png)]

注解

  • 请求方法 @POST
  • 标记类 @Streaming
  • 请求参数 @Body

Butterknife (注解模板代码)

依赖

android {
  ...
  // Butterknife requires Java 8.
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {
  implementation 'com.jakewharton:butterknife:10.2.1'
  annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'
}
buildscript {
  repositories {
    mavenCentral()
    google()
   }
  dependencies {
    classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.1'
  }
}
//apply plugin: 'com.android.library' 高版本的Android studio 内部集成了
apply plugin: 'com.jakewharton.butterknife'

使用

  • 绑定布局

    ButterKnife.bind(this); this是指activity的Context

  • 点击事件

      @OnClick(R.id.button)
        public void changeText(){
            textView.setText("文字更改");
        }
    
  • 绑定控件

     @BindView(R.id.text_change)
     public TextView textView;   //一定是private
    
    
  • 绑定资源

     @BindString(R.string.app_name)
     public String changeText;
    
    

  • 在fragment里面绑定布局

    记得在onCreateView里面绑定布局

    @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fancy_fragment, container, false);
        ButterKnife.bind(this, view);
        return view;
      }
    
  • 在adapter里面绑定布局

    记得在ViewHolder里面绑定布局

    static class ViewHolder {
        @BindView(R.id.title) TextView name;
        @BindView(R.id.job_title) TextView jobTitle;
    
        public ViewHolder(View view) {
          ButterKnife.bind(this, view);
        }
      }
    
  • 多控件绑定 使用大括号包含控件集合

  • 可选绑定

    @Nullable和@Optional 控件不存在接不存在

GreenDao (数据库)

依赖

buildscript {
    repositories {
        jcenter()
        mavenCentral() // add repository
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.3'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
    }
}
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
 
dependencies {
    implementation 'org.greenrobot:greendao:3.2.2' // add library
}

注解

  • @Entity 实体
  • @Id 主键Long @Id(autoincrement = true)设置自增长
  • @NotNul 不为空
  • @Transient 不生成数据表的列
  • @Index 索引
  • @Unique唯一约束
  • @ToOne 和另一个实体关联
  • @ToManny 和多个实体关联

使用

  • 创建Bean

    构建项目自动生成模板代码

    @Entity
    public class User {
        @Id
        private Long id;
        private String name;
        private int age;
    
       //下面省去了 setter/getter
    }
    
  • 创建 DBManager

    数据库管理

Glide (图片加载-支持GIF)

依赖

implementation 'com.github.bumptech.glide:glide:4.11.0'
  annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

使用

  • 基本使用

Glide.with(this).load(imageURL).into(imageView);

  • recycleView Adapter中使用Glide

    @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (null == convertView) {
                convertView = inflater.inflate(R.layout.listview_item_image, parent, false);
            }
    
            Glide
                .with(context)
                .load(imageUrls[position])
                .into((ImageView) convertView);
    
            return convertView;
        }
    

功能

  • 必要的三个参数

    • with(context)
    • load(url)
    • into(imageview)
  • 多源加载

    • 网络资源
    • 本地资源
    • 文件
    • uri
  • 缓存实现基于Picasso

    • 缓存实现大小依赖设备磁盘的大小: 内存 磁盘,网络
    • skipMemoryCache(true) 跳过内存缓存 [就是不会把图片缓存在内存里]
    • diskCacheStrategy 磁盘缓存
  • 图片占位符

    • glide在加载图片的过程中imageview是空白的
    • placeholder(url) 加载成功之前显示的图片
    • erro(url)加载错误的时候显示的图片
  • 淡入淡出

    • crossFade()
    • dontAnimate() 取消淡入淡出
  • 缩放

    • rtuesize(x,y)
    • override(x,y)
    • centercrop() 图片不完全显示,大小等于imageview大小
    • fitcenter() 图片完全显示,大小可能不等于image view大小
  • 类型转换

    • asgif() 若图片url不是gif则加载失败
    • asbitmap() 如果是git则会显示第一帧
  • 视频

    • 仅仅可以试试本地视频
  • 请求优先级

    priority(Priority.LOW)

  • 缩略图

    • thumbnail 配合imageview的scaleType使用

RxAndroid (异步)

依赖

allprojects {
    repositories {
        maven { url "https://oss.jfrog.org/libs-snapshot" }
    }
}
dependencies {
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
    implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
}

概念理解

  • 响应式

    • 关注结果的变化
  • 观察者模式

    • Observable 被观察者 [行为可发生改变]
    • Observer 观察者 [知道行为改变之后做出响应动作]
    • Subscribe 订阅 [关联两者的关系]
    • 事件处理
      • onNext 一个事件处理
      • onComplete 事件处理完成
      • onError 事件处理错误
  • map

     .map(new Function<String, List<String>>() {
            @Override
            public List<String> apply(String query) {
              return mCheeseSearchEngine.search(query);
            }
          })
    
    • map 操作符对 observable 发出的每一个事件应用一次函数变换,返回另外的一个发出函数执行结果类型事件的 observable
  • filter

    return textChangeObservable
        .filter(new Predicate<String>() {
          @Override
          public boolean test(String query) throws Exception {
            return query.length() >= 2;
          }
        });
    
    • filter 操作符, 防抖动, 对 observable 发出的事件进行过滤。但是决定事件该不该被过滤掉的原则不是靠判断发出的是什么事件,而是取决于何时发出的事件
  • merge

    Observable<String> searchTextObservable = Observable.merge(textChangeStream, buttonClickStream);
    
    • 接收两个或更多 observable 发出的事件,然后将它们放入一个 observable 中处理

线程模型

  • 控制线程模型 [observabel的方法]

    • subscribeOn 指定被观察者(Observable)自身在哪个调度器上执行
    • observeOn 指定一个观察者(Observer)在哪个调度器上观察这个被观察者(Observable)
  • Schedulers.trampoline()将任务加入一个队列,等待执行

  • Schedulers.newThread()每次都创建新的线程执行操作;

  • Schedulers.immediate()在当前线程运行,默认为此策略;

  • Schedulers.io(): 适合在 I/O 线程的工作,例如网络请求或磁盘操作。

  • Schedulers.computation(): 计算性的任务,比如事件轮循或者处理回调等。

  • AndroidSchedulers.mainThread() 在主线程中执行下个操作符的操作。

使用

  • 创建被观察者

    需要处理那些事件

     Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
                @Override
                public void call(Subscriber<? super String> subscriber) {
                    subscriber.onNext("我叫小锋锋  "+Thread.currentThread().getName());
                    subscriber.onCompleted();
                }
            });
    
    
  • 创建观察者

处理事件的具体逻辑

Observer<String> observer = new Observer<String>() {
            //事件处理逻辑
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted: 完成!");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError: 错误");
            }

            @Override
            public void onNext(String s) {
                Log.d(TAG, "onNext: 结果 "+s);
                textView.setText(s);
            }
        };

  • 调用

    指定 观察者 的线程模型 observeOn

    指定 被观察者 的线程模型 subscribeOn

 Subscription subscribe = observable
                .subscribeOn(Schedulers.io())//指定线程模型
                .doOnSubscribe(new Action0() {
                    @Override
                    public void call() {

                    }
                })
                .observeOn(AndroidSchedulers.mainThread())//指定线程模型
                .subscribe(observer);//通知,观察者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值