1.Token
首先Token是一个怎么样的东西,Token存在的意义又在哪里?学过php或是其他web开发的人都知道一个东西叫session和cookie,这些东西可以在服务器或是本地保存一些东西,比如说登录状态,当用户登录后可以通过session或是cookie在本地保存一段时间的登录状态,在这段时间内,用户再度登录的时候就不用再输入用户名和密码了,但是过了一段时间后,用户需要再次进行身份认证,这样一来的话,一方面节省了很多操作的步骤提升了操作体验,同时也节省了很多服务器请求,提高了服务器性能,同时也保证了一定的安全性。
那么这个功能如何在android中实现呢?很可惜的是在android中并没有直接提供类似session或cookie的东西,这个时候就是通过Token来完成。Token的存在更像是一个令牌,比如说当我们需要实现具有用户权限的操作时,每一次操作都需要向服务器发送请求,让服务器完成在数据库中进行用户名和密码,这些显然对于服务器的性能是很不利的。当然有人也会说我们可以在一次请求成功后将类似于user_id的东西保存在本地,以后每次请求的时候用user_id进行操作,这样不是就降低了服务器的负担,但是这样的话存在一个问题,就是user_id一旦存储在本地的时候,不是太有可能会自动回收掉,这样一来的话就会导致一个问题,就是app无论何时打开都是验证通过的状态,这样一来安全性降低。而Token就是解决这样一个问题的东西:
Token的定义:Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
2.Throwable:所有已实现的接口
3.key-value 键值对 和4绑定讲解
- key 需要存的值的编号 Token
- value 需要存放的数据 dhjwejrdgwjefhjqtwjkawlfi8a34
4.CacheUtil缓存工具类
CacheUtil中的存取方法
具体使用方法--LoginActivity
- 在 “登陆”按钮的点击事件中传入
【注意⚠️】
如果 “类.方法”的时候,方法出不来,那就说明,该方法还没有被定义为静态类,还不可以被调用。那就需要返回工具类中,将该方法改为静态类的
CatheKey.TOKEN -- RetrofitFactory--自定义网络拦截器--获取本地缓存的token
- getInstance()--外部获取实例对象
- 在 TaskGoApplication.java文件中
- CatheKey.java
5.面向对象
原网址:https://www.cnblogs.com/dotgua/p/6354151.html?utm_source=itdadao&utm_medium=referral
1.extends与implements
- 一个子类只能拥有一个父类->类的继承是单一继承
- extends只能继承一个类
- implements实现多继承特性,继承多个接口
- 接口与接口之间采用逗号分隔
2. super与this
- super:实现对父类成员的访问,用来引用当前对象的父类
- this: 指向自己的引用
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 调用自己的方法
super.eat(); // super 调用父类方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
输出结果:
animal : eat
dog : eat
animal : eat
3.final和static
- final
- 将类定义为不可继承的,即:最终类
- 或用于修饰方法,表明该方法不能被子类重写
- 变量加final就变成常量,不可被改变
【注】: 1.被final定义的类和这个类里面的变量是两回事,final定义类的时候,对类里面的变量没有任何影响,调用final类的方法对变量也没有任何影响 2.被声明为final类的方法自动的声明为final,但实例变量并不是final
- static修饰成员变量 + static关键字可以修饰成员变量和方法,来让它们变成类的所属,而不是对象的所属(对象是类的实例),解释👇
public class Person {
String name;
Int grades;
static int class;
}
实例化 20个Person对象,那就有了40个不同的 name 和 grades
但是 全全部部只有一个 class
- static修饰成员方法
- "类名.方法名"调用该静态方法
如果在一个类中,某方法不是静态方法(非static修饰),那就不可以通过"类.方法"进行调用
- static修饰静态块
- 创建对象时,static修饰的成员会首先被初始化
- static修饰的成员变量首先被初始化,随后是普通成员,最后调用类的构造方法完成初始化
- 创建对象时,static修饰的成员会首先被初始化
4. 重写与重载
- Overloading
- 方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载
- Overriding
- 方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写
- 方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现
5.多态和虚方法
安卓多态运用--自定义图形:http://blog.csdn.net/qq_32985981/article/details/50173503
6.封装--对数据的隐藏
- 控制那些是自己所私有,哪些可以被共享使用
- 外部用户只需要关心该类的功能和对象,不需要关心具体的实现过程和数据
7.Path 和Query
- 有问号的使用Query
- 只有 {...} 的使用Path
8.为了缓存新用户的Token
是想注册的接口后 调用 登录接口
因为Token的保存是在登录的接口上
9.线程问题
- 由于等用户注册后直接进入主界面,不需要再次进进行登录界面的相关操作,但是Token只能在登录的时候进行本地缓存,所以⚠️⚠️,我们就可以在注册界面 再一次 调用登录的接口
坑:两个接口的调用,不能同时进行,不然开启就是两个线程同时进行,导致 一边Toast出来“此用户不存在”,一边 又直接进入了主界面
廖雪峰线程章节
1. 多线程
- 多线程:让任务交替执行
- 一个进程可以包含一个火多个线程
- 多进程稳定性比多线程稳定性高
- 一个进程的出问题,不影响其他进程
- 一个线程出问题,其他线程也会死
2.创建新线程
- 程序本身无法控制线程的先后顺序
- 必须使用 start() 方法才能启动新线程
- Thread.sleep()可以把当前线程暂停一段时间
8.Bundle
- 一种存放字符串等类型数据的map类型的容器类
- 通过存放数据键(key)获取对应的各种类型的值(value)
- 主要作用于Activity之间的数据传递
9.JAVA接口
1.接口与类的区别
- 接口不能实例化对象
- 接口没有构造方法
- 接口中所有的方法必须是抽象方法
- 接口不能包含成员变量,除了static和final变量
- 接口不是被类继承的,而是要被类实现的
- 接口支持多继承
2.接口特性
- 接口中的方法会被隐式的指定为public abstract
- 接口中的变量也会被隐式的指定为public static final 变量
- 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法
3.抽象类与接口
- 一个类只能继承一个抽象类,但是一个类能实现多个接口
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变只能是public static final类型的
- 抽象类中的方法可以有方法体,就能实现方法的具体功能,但是接口中的方法不行
4.当类实现接口的时候,来要实现接口中所有的方法,否则,类必须声明为抽象的类
5.一个接口能继承另一个接口,接口的继承使用extends关键字,自接口继承父接口
10.注意事项
- 被继承的类称为超类,派生类称为子类
- 包名所有字母小写
- com.runoob
- 类名每个单词首写字母大写,其他小写
- toString()
- 变量和方法:第一个字母小写,从第二个单词开始首字母大写
- meditPassWord
- 常量:所有字母大写,每个单词之间用 _ 连接
- GAME_COLOR="RED"
11.局部变量、实例变量、类变量
类变量:独立于方法之外的变量,用static修饰
成员变量:独立于方法之外的变量,不过没有static修饰
局部变量:类的方法中的变量
1.局部变量
- 声明在方法、构造方法或者语句块中
- 在方法、构造方法、与巨快被执行的时候创建,当执行完成后,变量将会被销毁
- 访问修饰符不能用于局部变量
- 局部变量值在声明他的方法、构造方法、语句块中可见
- 局部变量是在栈上进行分配的
- 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用【⚠️必须初始化】
【补充】
- 成员变量在堆内,局部变量在栈内
- 访问修饰符
- public
- private
- default
- protected
2.成员变量--实例变量--没有被static修饰的变量
- 声明在一个类中,但在方法、构造方法、语句块之外
- 当一个对象被实例化后,每个实例变量的值就跟着确定了
- 实例变量在对象创建的时候创建,在对象被销毁的时候销毁
- 实例变量的值应该至少被一个方法、构造方法、语句块引用,是的外部能够通过这些方法获取实例变量信息
- 实例变量可以声明在使用前或者使用后
- 访问修饰符可以修饰实例变量
- 实例变量对于类中的方法、构造方法、语句块是可见的。
- 一般情况下,应该把实例变量设为私有
- 通过访问修饰符可以使实例变量对子类可见
- 实例变量具有默认值
- int - 0 ; bool - false ; 引用类型变量 - null
- 变量的值可以在声明时指定,也可以在构造方法中指定
- 实例变量可以直接通过变量名访问。
3.类变量-静态变量-static
- 类中以static关键字声明,但必须在方法、构造方法、语句块之外
- 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝
- 静态变量在程序开始时创建,在程序结束时销毁
- 默认直通实例变量相似。
【补充】--final与static
- final -- 常数
- final修饰的属性跟具体对象有关,在运行期初始化的final属性,不同对象可以有不同的值
- final修饰的方法表示该方法在子类中不能被重写,final修饰的类表示该类不能被不能被继承
- final初始化后不能被改变,初始化的过程可以在编译期(类加载的时候)、运行期
- static -- 静态
- static初始化后仍可以改变
- 用static修饰的代码表示静态代码块,当Java虚拟机(JVM)加载类的时候就会调用这个方法
- static修饰的属性所有对象都只有一个值
- static强调 它们 只有一个
- static修饰的属性、方法、代码段跟该类的具体对象无关,不创建对象也能调用static的属性、方法、代码段
- static与 this/super 势不两立,因为 this/super与具体对象有关
- static不可修饰局部变量
12.break,continue,return
continue只是在一次循环中不继续向下进行,继续i++;而break是直接结束了本次剩下的全部i++,直接进入外部循环的j++中,而return是直接跳出了全全部不的循环
13.Java修饰符
private
public class logger{
privite String secret;
public String getSecret(){
return this.secret;
}
public void setSecret(String secret){
this.secret=secret;
}
}
- 因为logger类中的secret为私有变量,所以其他的类不能直接得到和设置该变量的值
获得 和 改变 私有变量的方法
定义的两个public方法:
- getSecret()--返回secret的值
- setSecret(String secret)--设置secret的值
【补充】
- 基类就是父类,Object类是所有类的父类,父类继承父类,继承并重写父类的方法和非私有变量成员
父类中声明为private的方法,不能够被继承
14.拷贝
static关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝
局部变量(类方法中的变量)是不能被声明为static变量的
15.将底部按钮均分位置
android:layout_weight="1"
16.src与background
- background--分割线view设置颜色
- src--图片的背景
17.设置点击底部按钮文字变色
在drawable中,重新编写 selector的XML文件
18.FragmrntUtil
public class FragmentUtil {
/**
* 添加Fragment
*/
public static void addFragment(BaseActivity context, int viewId, Fragment fragment, @Nullable String tag) {
context.getSupportFragmentManager()
.beginTransaction()
.add(viewId, fragment, tag)
.commit();
}
/**
* 替换Fragment
*/
public static void replaceFragment(BaseActivity context, int viewId, Fragment fragment, @Nullable String tag) {
context.getSupportFragmentManager()
.beginTransaction()
.replace(viewId, fragment, tag)
.commit();
}
/**
* 隐藏Fragment
*/
public static void hideFragment(BaseActivity context, Fragment fragment) {
context.getSupportFragmentManager()
.beginTransaction()
.hide(fragment)
.commit();
}
/**
* 展示Fragment
*/
public static void showFragment(BaseActivity context, Fragment fragment) {
context.getSupportFragmentManager()
.beginTransaction()
.show(fragment)
.commit();
}
}
- 添加Fragment
- 替换Fragment
- 隐藏Fragment
- 展示Fragment
每次点击底部按钮的时候,需要先将全部的Fragment进行隐藏
/**
* 隐藏所有fragment
*/
private void hideAllFragment() {
if (mHomeFragment != null) {
FragmentUtil.hideFragment(this, mHomeFragment);
}
if (mMessageFragment != null) {
FragmentUtil.hideFragment(this, mMessageFragment);
}
if (mMineFragment != null) {
FragmentUtil.hideFragment(this, mMineFragment);
}
}
19.给背景设置透明度--#XXXXXXe5
android:background="#1F9DD5e5"
20.底部按钮被覆盖事件
原因分析:Relativelayout布局中,需要添加一条重要的属性--above
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frame_content"
android:layout_above="@id/view_divider"
>
</FrameLayout>
<View
android:id="@+id/view_divider"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_above="@id/ly_bottom_menu"
android:background="@color/colorPrimary"
/>
由于不是Linealayout,没有vertical的orientation,所以需要自己手动排布局,利用above等属性
21.报错--空指针异常!判空!判空!判空!
一定需要有if-else 的判空操作
@OnClick(R.id.ly_menu_home)
public void onLyMenuHomeClicked() {
changeHomeMenuStatus();
hideAllFragment();
if(mHomeFragment==null){
mHomeFragment=new HomeFragment();
FragmentUtil.addFragment(this,R.id.frame_content,mHomeFragment,null);
}
else{
FragmentUtil.showFragment(this,mHomeFragment);
}
}
22.FrameLayout与Fragment
23.align相对布局问题
- android:layout_alignLeft="@id/xxx"
- 将控件的左边缘和给定ID控件的左边缘对齐
- android:layout_alignTop="@id/xxx"
- 将控件的上边缘和给定ID控件的上边缘对齐
- android:layout_below="@id/xxx"
- 将控件置于给定ID控件之下
- android:layout_toRightOf="@id/xxx"
- android:layout_toRightOf="@id/xxx"
24.ViewFlipper
25.Fragment中获取上下文Context一般用getActivity
应该将HomeFragment.this替换为getActivity()
getContext和getActivityhe和MainActivity.this和this
- this--表示当前对象,一般而言,在哪个类中调用,就是指向该对象
- MainActivity.this--表示MainActivity对象,一般用在内部类中指示外面的this,如果在内部类中直接用this,指示的是内部类本身。
- getContext()--这是View类中提供的方法,在继承了View的类中才可以调用,反悔的时候当前View运行在那个Activity的Context中
- getActivity()--获得Fragment所依附的Activity对象
- 但需要注意:这个方法当Fragment生命周期结束并销毁时getActivity()返回的是null,所以在使用时要注意判断null或者捕获空指针异常。
Activity继承Context
26.Bind自动生成Flipper的时候,需要提前将项目了中的文件名更改
报错报错还是报错:
原因是:xml文件中还没有更改过,所以自动生成的还是ViewFlipper
由于我们自己写了自定义的FlipperPage,需要在xml的文件中使用它
于是我们更改为这样:
回到HomeFragment文件中对layout进行generate,就自动Bind了
27.联合主键
先排前面再排后面
28.20180326旁听安卓课--详情见笔记
29.不同类-重写,同一类-重载
子类继承父类就叫做新的一类,就叫做不同类
30.纠正:setXXX 是重载的体现
多态的三大特性:重载、重写、接口
面向对象的三大特性:继承、多态、封装
31.两个startActivity并不是报错,更不是空指针异常,这是错误的❌
两个startActivity最多就是,点击一次性进入新的Activity,回退的时候需要点击两次后退按钮而已
32.私有变量的获取
除了get方法,还可以缓存到本地,用的时候取出来就行了
33.接口与abstract类
- 抽象类中的方法都是abstract的,但abstract类中的方法可以多种多样
- 实现接口要实现类中的所有方法,但是abstract中的方法不需要全部实现
34.@Override--ctrl+O 万能啊
35.Error:关于ActionBar的问题--already has an action bar
借鉴:http://www.cnblogs.com/hh9601/p/6404728.html
java.lang.IllegalStateException:
This Activity already has an action bar supplied by the window decor. Do not request Window.
FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme t
问题原因:当在activity中调用了setSupportActionBar(toolbar);
回到我的项目了文件中发现,这里确实出现了两个Bar同时存在的情形
回到AndroidManifest.xml 对应的Activity标签的android:theme中
进一步,到style中深究
于是我们换成NoActionBar
回看xml文件--成功
ok 我很喜欢
36.Toolbar取代ActionBar
借鉴网址:https://blog.csdn.net/zwlove5280/article/details/52771998
关键几个步骤:
1.在 Activity 中,用 Toolbar 取代 ActionBar(demo中将这一步封装在了BaseToolbarActivity中)
2.具体使用方法
37.Fork-Github
有一个叫做Joe的程序猿写了一个游戏程序,而你可能要去改进它。并且Joe将他的代码放在了GitHub仓库上。下面是你要做的事情:
https://linux.cn/article-4292-1-rss.html
38.SwipeRefreshLayout
https://github.com/PingerOne/SwipeRefreshDemo
【注意】
- 在这个布局里面只能包含一个子控件,而且是可以滑动的(因为要达到刷新的目的),如:RecycleView、ListView
- 主要方法👇
39.太机智了--BaseModel一个,利用重载,实现多个范型T都可以调用
40.Android Device Monitor--查看布局
41. .show很重要,不然Toast无限显现
在fragment中使用Toast.makeText()
Toast.makeText(getActivity(),"此功能暂时无法使用",Toast.LENGTH_SHORT).show();
42.abstract
无法实现一个抽象类,但是可以实例化一个抽象类的子类
43.如果一个抽象类没有字段,所有方法全部都是抽象方法,就可以把抽象类改写为接口
抽象类什么都可以做,为什么还要接口呢
一个类可以实现多个接口,但是只能继承一个类
44.内部类--在一个类中的类
1.成员内部类
class heaijia{....}
👆 heaijia 这就是名字 !!有名字的类
2.静态内部类
3.局部内部类
4.匿名内部类--special--crazy
今天,我遇到了 OnClickListener()居然是以匿名内部类的形式实现的,我惊了
45.Error:ArrayAdapter requires the resource ID to be a TextView
参考:https://blog.csdn.net/zsr0526/article/details/53224064
解决办法: 将R.layout.XXX这个布局文件XXX的根节点改成TextView
根结点
46.Error :Fragment获取上下文报错
Fragment不是上下文类,所以不能直接采用this,而是利用getActivity().getApplicationContext()
借鉴:https://stackoverflow.com/questions/35816602/argument-this-doesn%C2%B4t-work-required-android-content-context
47. Error:Adapter adapter
经我测试发现,将RecyclerView换成ListView就没有报错了,具体的原因还不知道是为什么
48.Error:点击button就闪退,ListView无法显示,并且在logcat中没有明显的蓝色报错信息
layout文件中的包含关系出了问题,导致recyclerView无法显示
49.ListView
借鉴:https://www.cnblogs.com/chenyuwei/p/4581700.html