<TextView
<!-- 宽度根据父级设置-->
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
<!-- 根据里面内容自动计算宽高-->
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#2000FF00"
设置颜色 RGB 每两位一组 顺序是 红绿蓝
FF0000 就是红色
想要半透明 #50FF0000 这么设置
可以设置图片 也可以设置图片
android:background="#fff0000"
设置居中
android:gravity="center"
阴影设置
android:shadowColor="@color/black" 颜色
android:shadowRadius="0.1" 模糊度
android:shadowDx="20" 偏移
跑马灯
android:singleLine="true" 文字不换行
android:ellipsize="marquee" 边界省略
android:marqueeRepeatLimit="marquee_forever" 滚动次数
android:focusable="true" Android TextView 是否可以获得焦点
android:focusableInTouchMode="true" Android TextView 是否可以在触摸模式下获取焦点
进入页面直接开始滚动
在双标签中加入

Button
根据不同样式设置不同效果

单击按钮的样式变化 按下一个显示 松开一个显示
使用drawable 下面新建一个rescource资源
1

2
在资源下新建item项 并设置两种样式 一种单击下的图片 一种不点击的样式
(要设置为图片)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/baseline_accessible_24" android:state_pressed="true"/> //点击变成这个
<item android:drawable="@drawable/baseline_accessible_forward_24"/>
</selector>
还可以设置颜色选择器 比如按下红色 默认黑色
- 1 在res新建一个color文件夹
- 2 创建rescource文件 item项目
android:backgroundTint="@color/btn_color_change"
进行单击改变颜色的切换
Button 事件处理
三种时间
1单击事件
2 长按事件
3 触摸事件
Button btn = findViewById(R.id.btn);
//点击事件
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//
}
});
//长按事件
btn.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
return false;
}
});
// 触摸时间
btn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
});
当return 为true时,其他的方法不会再被调用了
编辑框 EditText
主要属性

ImageView

processBar 进度条

Notification与NotificationManger
通知管理类,单例方式模式
import android.app.NotificationManager;
import android.content.Context;
import android.support.v4.app.NotificationCompat;
public class MyNotificationManager {
private static final int NOTIFICATION_ID = 1;
private static final String CHANNEL_ID = "my_channel_01";
private static final CharSequence CHANNEL_NAME = "My Channel";
// 显示通知的方法
public static void showNotification(Context context, String title, String message) {
// 获取 NotificationManager 实例
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// 使用 NotificationCompat.Builder 创建通知对象
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon) // 设置通知小图标
.setContentTitle(title) // 设置通知标题
.setContentText(message) // 设置通知内容
.setPriority(NotificationCompat.PRIORITY_DEFAULT); // 设置通知优先级
// 发送通知
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
// 取消通知的方法
public static void cancelNotification(Context context) {
// 获取 NotificationManager 实例
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// 取消指定 ID 的通知
notificationManager.cancel(NOTIFICATION_ID);
}
}

toolBar 最上方导航栏



如何让标题处于居中位置呢 ?
将toolbar设置为双标签,然后将textView文本放在中间 写上layout_gravity="center" 就居中了

AlertDialog


LinearLayout
纵向排列
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ff00"
android:orientation="vertical" 纵向布局
>
<LinearLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#00fff0"
></LinearLayout>
<LinearLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#f0ffff"
></LinearLayout>
<LinearLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#ff00ff"
></LinearLayout>
</LinearLayout>

android:gravity="center" 让其所有子元素布局方式
也可以加或语句进行复式用法 比如说居中又在底部
android:gravity="center | bottom"

分割线
android:divider="@drawable/baseline_arrow_back_ios_24" 边框线
android:showDividers="middle" 粗度
android:dividerPadding="100dp" 边距

<LinearLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#00fff0"
android:layout_weight="1" 权重进行空间分配(在原有的基础上)
></LinearLayout>
RelativeLayout

兄弟组件根据id来进行放置
写法为
android:layout_toRightOf="@id/l2"
margin 距离父元素距离 padding 距离内容距离
FrameLayout 帧布局
从左上角开始绘制
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:layout_width="400dp"
android:layout_height="400dp"
android:background="#ff0000">
</FrameLayout>
<FrameLayout
android:layout_width="300dp"
android:layout_height="400dp"
android:background="#fff000">
</FrameLayout>
</FrameLayout>

android:foreground="@drawable/btn_one" 设置前景色
android:foregroundGravity="right" 设置前景色位置
TableLayout 表格布局
默认独占一行
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:text="按钮"
>
</Button>
</TableLayout>

要放在tableRow中
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TableRow>
<Button android:text="按钮"/>
<Button android:text="按钮2"/>
</TableRow>
</TableLayout>

隐藏列
在tableLayout中使用属性android:collapseColumns="0"
0表示隐藏第一列 0,2 隐藏第1列和第3列
拉伸列
android:stretchColumns="0" 拉伸第一列的,铺满剩余空间。
收缩列
有超出部分不显示,可以设某一个列收缩
android:shrinkColumns="0"
子控件设置

GridLayout
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="3" 一行最多显示3列
>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
</GridLayout>

子控件属性

ConstrainLayout 约束布局

在这上面拖动
ListView
ListView 是 Android 中常用的一个列表视图控件,用于在界面上展示一系列的数据项。它可以用来显示垂直滚动的列表,每个列表项都可以包含一个自定义的布局。
要在布局文件中添加一个 ListView 控件,可以使用以下 XML 代码:
xml
Copy code
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
在代码中,您可以通过调用 findViewById() 方法来获取对 ListView 控件的引用,然后为其设置适配器,以便显示数据。
java
Copy code
ListView listView = findViewById(R.id.listView);
// 创建一个适配器并设置给ListView
ListAdapt adapter = new ListAdapt(dataList, context);
listView.setAdapter(adapter);
在上面的示例中,dataList 是要显示的数据列表,context 是当前的上下文对象。ListAdapt 是您自定义的适配器,用于将数据绑定到 ListView 上。
最后,您可以设置 ListView 的点击事件监听器,以便在用户点击列表项时执行相应的操作。
java
Copy code
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
// 处理点击事件,position 是被点击的列表项的位置
}
});
通过以上步骤,您就可以在 Android 应用程序中使用 ListView 控件来展示数据了。
RecyclerView
首先引入相关依赖
implementation 'androidx.recyclerview:recyclerview:1.1.0'
使用 RecyclerView 时,您需要执行以下步骤:
- 在布局文件中添加 RecyclerView 控件: 在您的布局文件(通常是 XML 文件)中添加一个 RecyclerView 控件,用于显示列表或网格数据。您可以使用以下代码示例添加一个 RecyclerView:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
创建列表项布局文件: 创建一个布局文件,用于定义 RecyclerView 中每个列表项的外观。例如,您可以创建一个名为
list_item.xml的布局文件。创建 RecyclerView 适配器: 创建一个适配器类,继承自 RecyclerView.Adapter,并实现必要的方法。适配器负责将数据绑定到 RecyclerView 上。
配置 RecyclerView 的布局管理器: 在代码中配置 RecyclerView 的布局管理器,以确定列表项是线性排列还是网格排列等。
设置适配器: 获取对 RecyclerView 控件的引用,并将适配器设置给它。
准备数据: 准备要在 RecyclerView 中显示的数据。这可能是一个列表或数组,其中包含您要显示的数据项。
以下是一个简单的示例,演示了如何在 Android 应用程序中使用 RecyclerView:
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private List<String> data = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 准备数据
data.add("Item 1");
data.add("Item 2");
data.add("Item 3");
data.add("Item 4");
data.add("Item 5");
// 获取对 RecyclerView 控件的引用
recyclerView = findViewById(R.id.recyclerView);
// 创建一个布局管理器并设置给 RecyclerView
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
// 创建一个适配器并设置给 RecyclerView
MyAdapter adapter = new MyAdapter(data);
recyclerView.setAdapter(adapter);
}
}
在这个示例中,我们使用了 RecyclerView 和 LinearLayoutManager。接下来,您需要创建适配器类 MyAdapter,并实现必要的方法,例如 onCreateViewHolder()、onBindViewHolder() 和 getItemCount()。以下是适配器类的示例:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<String> data;
public MyAdapter(List<String> data) {
this.data = data;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
String item = data.get(position);
holder.textView.setText(item);
}
@Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public ViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.textView);
}
}
}
在这个示例中,我们创建了一个简单的适配器类 MyAdapter,用于将数据绑定到 RecyclerView 上。我们还定义了一个内部 ViewHolder 类,用于保存每个列表项的视图。在 onBindViewHolder() 方法中,我们将数据绑定到 ViewHolder 中的视图上。
最后,您还需要创建列表项的布局文件 list_item.xml,用于定义每个列表项的外观。
动画
1 帧动画
几张图片进行快速播放
首先在drable创需一个xml文件

用的时候直接放在视图容器就OK

单位和尺寸
px像素 不同设备显示效果不同
因为每个屏幕的像素点不一样 如像素点多的手机 你设置10px很小
dip 设备独立像素 适配不同屏幕大小的单位
dp :随着屏幕的大小变化
sp 用于字体 scaled pixels (放大像素)
ViewPager 视图翻页器
下次学
MVVM

Fragment
可重用的界面组件的类。它代表了一个可嵌入到活动中的独立的用户界面部分,可以包含自己的布局、生命周期和行为。与活动(Activity)不同,Fragment 可以在同一个屏幕上同时存在多个,并且可以灵活地在不同的屏幕配置(如手机和平板电脑)中重用。
他是什么?
相当于vue中的框架
比如在同一页面中,左侧为列表,右侧为单击列表所显示的内容
相当于ipad中的布局

1.具备声明周期 相当于子activity
2.必须委托在activity中才能运行
activity生命周期结束 ,fragment结束.
然后在layout中创建fragment文件,在java中也创建一个framement_acticity来获取到layout的组件进行控制,然后返回
如何绑定到activity中呢
Fragmen_blank.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".BlankFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/textView"
android:layout_width="40dp"
android:layout_height="40dp"
android:text="@string/hello_blank_fragment" />
<Button
android:layout_width="match_parent"
android:layout_height="40dp"
android:id="@+id/tbn"
android:text="点击"/>
</LinearLayout>
Fragmen_blank.java
package com.lifang.project;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
/**
* A simple {@link Fragment} subclass.
* Use the {@link BlankFragment# } factory method to
* create an instance of this fragment.
*/
public class BlankFragment extends Fragment {
private View root;
private TextView textView;
private Button button;
// TODO: Rename and change types and number of parameters
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (root == null) {
root = inflater.inflate(R.layout.fragment_blank,container,false);
}
textView = root.findViewById(R.id.textView);
button = root.findViewById(R.id.tbn);
// btn 点击 修改文本内容
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.setText("变成新内容");
}
});
// Inflate the layout for this fragment
return root;
}
}
绑定在activity页面中进入小写的标签fragment 去引用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
>
<fragment
android:id="@+id/framgment" //使用必须有id
android:name="com.lifang.project.BlankFragment"//framgment创建位置
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
就是一个小型的activity.`
动态添加fragment
activity和fragment通信
使用Bundle
在mainactivity中
Bundle bundle = new bundle();
bundle.put("message","威威"); //此行代码是往fragment传递数据
blankFragment bf = new BlankFragmenet();
bf.setArguments(bundle);
在fragment.java中
在任何地方可以使用
Bundle bundle = this.getArguments();//来进行获取acticity里面传过来的参数
bundle.getString()
动态添加fragment
创建一个待处理的fragment
获取fragmentmanager,
开启一个事务 transaction
进行替换
提交事务
类与类用接口进行通讯
IFragmentCallback
public interface IFragmentCallBack {
//通过接口实现通讯
//fragment给activity发送信息
void sendMsgToActivity(String s);
String getMsgFromActivity(String s);
}
要完成通讯,现在fragment里面定义一个callback函数
private IFragmentCallback fragmentCallback;
//activity 给他赋值
public void setFragmentCallback(IFragmentCallback callback){
fragmentCallback = callback;
}
这样很麻烦 所以使用eventBus来进行.
生命周期


ViewPage的使用
相当于微信底部导航的切换页面


要实现微信底部导航按钮跟fragment联动效果,需要使用BottomnavigationView
二,activity 组件
activity 就是页面活动的跳转,比如从第几个页面跳转到第几个页面
他有他的生命周期

所有的activity组件都要在清单文件中注册。

三,service组件
服务在后台运行,是不可见的。
创建一个类,继承Service就是服务
三,广播 Receiver
- 系统广播
- 自定义广播
四,热修复
当应用上线后出现bug,不需要重新安装安装包,只需要发布补丁包,让用户没有感知的情况下进行更新
项目中引入Tinker来进行热修复
Bugly+Tinker实现热修复



五,引入高德地图SDK
Glide的图片加载库使用


网络请求失败的情况

网络请求加载框架
OkHttp与Retrofit
okhttp 处理网络请求的
implementation 'com.squareup.okhttp3:okhttp:4.9.0'加入到项目中
要进行权限注册在Manifest中
<uses-permission android:name="android.permission.INTERNET"/>

同步请求
public class MainActivity extends AppCompatActivity {
private static final String TAG ="MainActivity";
private OkHttpClient okHttpClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建网络请求的
okHttpClient = new OkHttpClient();
}
public void get(View view) {
//在安卓中要完成网络的请求必须有一个子线程来完成这个事情,要在线程中去完成这个同步请求的操作
new Thread(){
@Override
public void run() {
//创建request对象,交给请求工具okHttpClient
Request request= new Request.Builder().url("https://www.httpbin.org/get?age=18&name=hx").build();//上传参数使用? 键值对的方式 比如age=18
Call call = okHttpClient.newCall(request);// 准备好请求的call对象
//进行同步请求
try {
// 得到的响应数据
Response response = call.execute();
Log.i(TAG, "get: "+response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
get异步请求
public void getSync(View view) {
//创建request对象,交给请求工具okHttpClient
Request request= new Request.Builder().url("https://www.httpbin.org/get?age=18&name=hx").build();//上传参数使用? 键值对的方式 比如age=18
Call call = okHttpClient.newCall(request);// 准备好请求的call对象
//异步请求 enqueue里面自动有一个线程
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
//这里是与http响应成功 返回状态码,比如200 500 404等等200-300是成功 300-400重定向 400-500服务器错误
if (response.isSuccessful()) {
//成功
Log.i(TAG, "getaSync: "+response.body().string());
}
}
});
}
post异步请求
需要将请求参数放到请求体里面
public void postSync(View view) {
// post请求参数需要放在请求体里面
FormBody formBody = new FormBody.Builder().add("name", "cc").add("age", "22").build();
Request request= new Request.Builder().url("https://www.httpbin.org/post").post(formBody).build();
Call call = okHttpClient.newCall(request);// 准备好请求的call对象
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
Log.i(TAG, "postaSync: "+response.body().string());
}
});
}
其实就是封装了OkHttp,一个用来处理网络请求的开源项目.
一,首先根据http接口来创建Java接口

二,创建Retrofit对象,并生成接口实现类对象

三,接口实现类对象调用对应方法获得相应
retrofit2.Call<ResponseBody>call = httpbinService.post("hx", "123456");
call.enqueue(new retrofit2.Callback<ResponseBody>() {
@Override
public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
try {
Log.i(TAG, "postaSync: "+response.body().string());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
}
});
Retrofit注解分类

Retrifit转换器
在接到服务器的响应数据后,目前无论是okhttp还是retrofit都只能接收到String字符串类型数据,实际开发要对字符串进行解析变成java Bean对象,或者将java对象转换为json。使其进行相互转换。
我们拿到服务器给我们传过来的json响应数据,为了方便好拿数据,所以我们需要将json数据转换为为java bean对象的格式,你们就要创建出对应的java bean类.
1 引入自动转换依赖
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
** 2 **
public void LoginTest() throws IOException {
Call<ResponseBody> call = wanAndroidService.login("houx", "123456");
Response<ResponseBody> response = call.execute();
String result = response.body().string();
System.out.println(result);
//需要创建对应的java bean 类
BaseResponse baseResponse = new Gson().fromJson(result, BaseResponse.class);
System.out.println(baseResponse);
}
Retrifit适配器
在开发中,有很多请求会出现请求嵌套的.这样会出现回调地狱的情况,比如说我要请求收藏之前必须先登录

先请求A接口,再请求B接口.
可以使用RXjava来解决这个嵌套问题
1 引入依赖
implementation("com.squareup.retrofit2:adapter-rxjava3:2.9.0")
2
@Test
public void rxJavaTest() {
wanAndroidService3.login2("cc", "8483275876")
.flatMap(new Function<BaseResponse, Publisher<?>>() {
@Override
public Publisher<?> apply(BaseResponse baseResponse) throws Throwable {
return wanAndroidService3.getArticle(5);
}
})
.observeOn(Schedulers.io())//网络请求在一个单独的线程 io线程
.subscribeOn(Schedulers.newThread())//回调 切换到安卓主线程
.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Throwable {
}
});
}

这里的bean类不用自己一个一个写上去,可以借助BeJson工具,将json数据转换为Java Bean的格式.

使用转换器,那么就不需要自己去进行这个序列化和反序列的操作了。
post请求方式

拦截器

分别在拦截的前面执行或者拦截后执行
public class intercptor {
@Test
public void inter(){
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
//这是请求先走拦截器 还没有发送给服务器 在这里进行处理 所有请求都添加的信息
Request request = chain.request().newBuilder().addHeader("os","android").build();
//前置处理
Response response = chain.proceed(request);//
//后置处理 在response之前
return response;
}
}).addNetworkInterceptor(new Interceptor() {
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
return null;
}
}).build();
//创建request对象,交给请求工具okHttpClient
Request request= new Request.Builder().url("https://www.httpbin.org/get?age=18&name=hx").build();//上传参数使用? 键值对的方式 比如age=18
Call call = okHttpClient.newCall(request);// 准备好请求的call对象
//进行同步请求
try {
// 得到的响应数据
Response response = call.execute();
System.out.println("get: "+response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
缓存和cookie
okhttp支持缓存,当我们第一次发送请求时,之后还发送同样的请求,可以减少和服务器的通信,从本地拿取.

Gson
是一个轻量级数据交换格式
用来java对象和json数据之间进行映射的Java类库,可以将java对象转换为json字符串
为什么要进行后端与前端的数据格式交换呢
在与前端进行数据交互时,常常需要将Java对象转换为JSON格式发送给前端,或者接收前端传递的JSON数据并转换为Java对象进行处理。
并且json数据·JSON数据相对于其他格式(如XML)来说,数据体积通常更小,传输效率更高,节省带宽和资源。·
android的依赖引用使用
implementation'com.google.code.gson:gson:2.8.6'
使用Gson实现序列化和反序列化

public void test(){
User user = new User("hx",22,true);
Gson gson = new Gson();
String json = gson.toJson(user);
System.out.println(json);
}

.将json字符串转换为java对象
User u2 = gson.fromJson(json,User.class);
Array数组的序列化和反序列化
也是使用toJson 和 fromJson来进行

Map和Set 的序列化和反序列化
需要使用TypeToken完成反序列化

六,RX思维(reactivex)
响应式思维
根据上一层的响应,影响下一层的变化
6.1 使用Rxjava进行下载图片
package com.lifang.rxjava;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
public class MainActivity extends AppCompatActivity {
private static final String PATH = "https://img1.baidu.com/it/u=604096226,2356671358&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=500";
//加载框
private ProgressBar progressBar;
private ImageView img1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取进度条
progressBar = findViewById(R.id.progressBar);
//获取图片
img1 = findViewById(R.id.img1);
}
public void onLoadImg(View view) {
/**
* RX 思维
* 只有起点->终点 被观察者 观察者
*/
//起点
Observable.just(PATH)
//关联
//需求 下载图片
.map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(String path) throws Exception {
try {
URL url = new URL(path);
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
//设置请求时长 5秒不成功就是请求失败
httpURLConnection.setConnectTimeout(5000);
int responseCode = httpURLConnection.getResponseCode();//拿到服务器响应 200成功
if (responseCode == HttpURLConnection.HTTP_OK) {
//请求成功 服务器响应200
InputStream inputStream = httpURLConnection.getInputStream();//拿到这个输入流
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);//解流
// 将bitmap向下一层流下去
return bitmap;
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
})
//给上层分配异步下载 图片下载操作
.subscribeOn(Schedulers.io())
//终点分配安卓主线程
.observeOn(AndroidSchedulers.mainThread())
//终点
.subscribe(new Observer<Bitmap>() {// <String> 为什么是String ,上层响应影响下层变化
//订阅成功
@Override
public void onSubscribe(Disposable d) {
performTaskWithDelay();
}
// 拿到上层给的响应
@Override
public void onNext(Bitmap bitmap) {
img1.setImageBitmap(bitmap);//显示到控件上
}
// 链条思维发生异常
@Override
public void onError(Throwable e) {
}
//整个链条全部结束
@Override
public void onComplete() {
progressBar.setVisibility(View.INVISIBLE);
}
});
}
private void performTaskWithDelay() {
// 显示 ProgressBar
progressBar.setVisibility(View.VISIBLE);
// 模拟耗时操作
// new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
// @Override
// public void run() {
// // 完成任务后隐藏 ProgressBar
// progressBar.setVisibility(View.INVISIBLE);
// }
// },3000); // 模拟3秒的耗时操作
}
}
优点:可以在起点和终点之间增加需求,有需求添加一个.map()。
常用操作符,比如遍历数组
可以使用起点和终点的这种形式。

自定义解决Observer解决项目中服务器响应的问题
开发中,测试环境下登录功能没问题,但在正式环境下登录功能有问题
响应后服务端给我们响应的数据,然后我们从中只想拿到我们想要的数据
