Leetao's Blog

Talk is cheap, show me the code

0%

创建测试表

这里创建两张测试表

创建 test_provinceid 表

1
2
3
4
5
6
7
8
CREATE TABLE `test_province` (
`id` CHAR(2) NOT NULL,
`pname` CHAR(6) NOT NULL,
PRIMARY KEY (`id`)
)
COMMENT='省份'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

创建 test_cityid 表

1
2
3
4
5
6
7
8
9
CREATE TABLE `test_city` (
`id` CHAR(2) NOT NULL,
`pid` CHAR(10) NOT NULL,
`cname` CHAR(10) NOT NULL COLLATE 'latin1_swedish_ci',
PRIMARY KEY (`id`)
)
COMMENT='城市'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

插入测试数据

1
2
3
4
5
6
7
INSERT INTO `test`.`test_province` (`id`, `pname`) VALUES ('AH', '安徽省');
INSERT INTO `test`.`test_province` (`id`, `pname`) VALUES ('ZJ', '浙江');
INSERT INTO `test`.`test_province` (`id`, `pname`) VALUES ('HN', '河南');
INSERT INTO `test`.`test_city` (`id`, `pid`, `cname`) VALUES ('01', 'AH', '合肥');
INSERT INTO `test`.`test_city` (`id`, `pid`, `cname`) VALUES ('04', 'AH', '六安');
INSERT INTO `test`.`test_city` (`id`, `pid`, `cname`) VALUES ('02', 'HN', '郑州');
INSERT INTO `test`.`test_city` (`id`, `pid`, `cname`) VALUES ('03', 'HB', '石家庄');

数据库中 test_province 数据现在有如下这些:

数据库中 test_city 数据现在有如下这些:

左连接

语法

1
2
3
SELECT *
FROM a LEFT JOIN b
ON a.key = b.key

左连接以左边的表作为主表,这里我们以 test_province 为主表,查看一个省份在 test_city 中有哪些城市

测试

1
select * from test_province a LEFT JOIN (select * from test_city) b on a.id = b.pid

执行结果


注意:这里将省份存在,城市不存在的数据也显示出来了

右连接

语法

1
2
3
SELECT *
FROM a RIGHT JOIN b
ON a.key = b.key

有上述的左连接的认知,我们不难得出,右连接是以右边的表作为主表的认识,这里我们将上面的语句简单修改一下

测试

1
select * from test_province a RIGHT JOIN (select * from test_city) b on a.id = b.pid

执行结果


注意:这里将城市存在,省份不存在的数据也显示出来了

内连接

语法

1
2
3
SELECT *
FROM a INNER JOIN b
ON a.key = b.key

左连接以左边的表作为主表,有连接以右边的表作为主表,还差一个以双方作为主表的连接,那就是内连接啦,内连接的想法很简单,你有我有大家都有才是真的有,同样简单修改一下语句

测试

1
select * from test_province a INNER JOIN (select * from test_city) b on a.id = b.pid

执行结果


注意: 这里只显示了城市和省份想匹配的数据

单例模式的定义

维基百科的定义

In software engineering, the singleton pattern is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects.

翻译后的意思

在软件工程中,单例模式是一种设计模式,它限制了一个类的只能实例化出唯一一个对象。这是十分有用的尤其一个对象需要协调整个系统运作.这个概念在有的时候会被广义的认知当且仅当只有一个对象存在是,系统将运行的更加有效率或者将对象的实例化限制在一定的数量下.

单例模式的 UML 类图

从上面的类图可以看出,单例模式中有一个构造函数 Singleton,但是这个构造函数是私有的 (‘-‘ 符号代表私有变量),然后有一个公有的方法 getInstance()
看完 UML 类图,接下来让我们实现一个简单的单例模式

单例模式的实现

java 的单例模式

1
2
3
4
5
6
7
pubic class Singleton{
private static final Singleton instance = new Singletion();

public static Singletion getInstance() {
return instance;
}
}

java的单例模式有七种写法,这里就不一一列举了,可以参考java 单例模式的七种写法

单例模式的特点以及应用场景

从上述 UML 类图以及代码不难总结出单例模式有以下特点:

  1. 单例模式下该类有且只有一个实例
  2. 单例模式下该类自己创建自己的唯一实例
  3. 单例模式下该类必须给其他对象提供获取该实例的方法

单例模式的应用可以从单例模式的优点说起,由于单例模式在系统运行过程中只存在唯一一个实例对象,可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能,在实际应用中 数据库通常使用单例模式较多,避免重复连接数据库造成资源的浪费

virtualenv 的安装

Ubuntu 下 virtualenv 的安装

Ubuntu 下的安装 python 的第三方依赖库就不得不提 python 的三大神器之 pip.默认情况下 Ubuntu 是没有安装的,可以在命令行下使用pip xxx 进行简单测试.

pip 的安装

pip 安装有很多方法,最简单的就是命令行输入下列命令,然后回车

1
sudo apt-get install python-pip

当然还有其他的安装方式,可以参考How to install pip

pip 安装完成之后,接下来就是重头戏了.

virtualenv 的安装

在命令行下输入如下命令,然后回车

1
sudo pip install virtualenv

同样安装方法有很多种,可以参考How to install virtualenv

virtualenv 的简单入门

创建虚拟环境

1
virtualenv ENV

创建一个名为 ENV的文件夹,在创建环境时会依赖系统环境的site-packages,如果想完全不依赖系统的site-packages,可以加上参数–no-site-packages来建立虚拟环境.
然后进入到ENV的目录下,目录下有如下文件夹:

1
2
$:~/ENV$ ls
bin include lib local pip-selfcheck.json

激活虚拟环境

1
source bin/activate

激活成功后,命令行前面会出现**(ENV)**的符号,如下图所示:

注意:

  1. ENV/libENV/include 包含了该环境下所支持的库.在当前环境下安装的包将会保存在 ENV/lib/pythonX.X/site-packages
  2. ENV/bin 则是 编译器所在之处了,在当前环境下你的 python 脚本文件的头部写法应该是这样的 #!/path/to/ENV/bin/python
  3. 在 virtualenv 环境下 pip 和 setuptools 是默认安装的,然后你可以很容易的安装其他的三方库

退出虚拟环境

1
deactivate

Windows 下 virtualenv 的安装

windows 下安装 virtualenv 跟Ubuntu下安装大同小异,实现安装好 pip,然后将其路径添加到系统环境变量,然后紧接着安装 virtualenv ,然后完成之后尝试在任意路径新建新的虚拟环境了.

为什么要使用 virtualenv

老实说最初我并不怎么喜欢使用 virtualenv,但是随着后来写的代码越来越多,项目所依赖的第三库也各不相同,需要别人去协助的我的时候,由于没有使用virtualenv,导致本地的 python 中的三方库十分的多,这样导致还需要人工去判断当前项目使用哪些库何其麻烦.而 virtualenv 的作用就是用来建立一个虚拟的python环境,一个专属于项目的python环境,保持一个相当干净的环境
使用 virtualenv 后导出已安装的包,只需要如下命令:

1
pip freeze > <目录>/requirements.txt

然后别人安装你的依赖,也只需要一个简单的命令:

1
pip install -r requirements.txt

使用的PHP版本:5.5.12

PHP中关于 比较运算符有很多个,这里就不一一列举,不过今天在程序中使用了类似下面的代码,然后出现的错误

1
2
3
if($variable1 <= $variable2 <= $variable3){
//coding ...
}

错误信息

1
Parse error: syntax error, unexpected '<=' (T_IS_SMALLER_OR_EQUAL)

然后尝试将中间的比较运算符,换成其他的比较运算符,仍然出现相同错误,最后将代码修改为

1
2
3
if(($variable1 <= $variable2) && ($variable2 <= $variable3)) {
//coding...
}

获取combobox选中的值,文本

1
2
$('#com').combobox('getValue') //获取当前选中的值
$('#com').combobox('getText') //获取当前选中的文字

combotree设置默认值

1
$('#combotree').combotree('setValue',value);

禁用与启用combobox

1
2
$('#combobox').combobox('disable',true)
$('#combobox').combobox('enable')

combobox的隐藏与显示

1
2
$('#combobox + .combo').hide()
$('#combobox + .combo').show()

获取textarea的值

1
$('#textarea').val()

禁用与启用textarea

1
2
document.getElementById('textarea').disabled=true;
document.getElementById('textarea').disabled=false

获取textbox的值

1
$('#textbox').val()

禁用与启用textbox

1
2
$('#textbox').textbox('disable',true)
$('#textbox').textbox('enable')

linkbutton的禁用与启用

1
2
$('#linkbutton').linkbutton('disable');
$('#linkbutton').linkbutton('enable');

form的清空

1
$('#form').form('clear');

禁用整个form里面的输入框

1
2
$("#Form :input").attr("readonly", "readonly");
$("input").attr("readonly", "readonly");

validatebox的禁用与启用

前两种适用于单个的validatebox;

1
2
3
4
$("#id").attr("readonly", true); 
$("#id").removeAttr("readonly");
$("#id").attr("readonly", "readonly");
$("#id").removeAttr("readonly");

清空validatebox的值

1
$('#id').val("")

datebox禁用启用方法

1
2
$("#datebox").datebox('disable'); 
$("#datebox").datebox('enable');

datetimebox禁用启用方法

1
2
$("#datetimebox").datetimebox('disable');
$('#datetimebox').datatimebox('enable');

TextArea禁止拉动拖动改变大小

  1. 彻底禁用拖动:在sytle中添加resize:none
  2. 固定大小,右下角拖动图标依然存在
    1
    2
    3
    4
    width: x
    maxwidth: y
    height: mx
    maxheight: my

之前写Python的时候,用到了装饰器,然后不由自主想到了设计模式中的装饰模式,正好最近一直在看设计模式,就记录下自己的一些理解。如有错误,欢迎指正。

装饰模式

比较官方的定义是这样的

装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象

装饰,装饰嘛,很显然你只想让别人看见最终装饰的东西,并不像让别人看见你的装饰过程。打个比方说,你去餐馆吃饭,很明显主要是吃饭,当然光吃米饭,肯定难以下咽了,你想了想准备吃青椒肉丝盖浇饭,然后餐馆厨房开始做了,这个时候你想去厨房去瞧一瞧,你发现厨房门上贴着“非工作人员入内”,意思很明显嘛,餐馆并不希望我去参观他做盖浇饭的过程,谁知道中间有什么猫腻,最后呈现在我面前的就是我自己点的那份青椒肉丝盖浇饭,当然盖浇饭不止这一种还有番茄鸡蛋盖浇饭啊,鱼香肉丝盖浇饭啊。。。不过厨房加工的地方不让看。

类图是这样的:

可以把Component看作一个食物,ConcreteComponent看作米饭,Decorator则可以看作加工过程,ConcreteDecoratorA(B)就是各种食物素材啦。
对于Componet是无需知道Decorator存在的。
如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样如果只有一个ConcreteDecorator
,那么也没有必要建立一个单独的Decorator,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

这个时候的类图,如下:

和这样

顺便说下starUML类图中部分符号的含义:

  1. 类 ( Class ) :三层矩形框表示,第一层类名,如果是抽象类,是用斜体表示的;第二层是字段和属性;第三层则是类方法,其中”+”表示该方法是public的,“-”表示private,“#”表示protected
  2. 继承类():用空心三角形+实现来表示

Talk is cheap,show me the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php
abstract class food
{
public $_name;
abstract public function cook();
}

//被装饰的类
class rice extends food
{
public function __construct()
{
$this->_name = 'rice';
}

public function cook()
{
return "cooked_rice";
}
}

//盖浇饭decorator
class fooddecorator extends food
{
public function __construct()
{
$this->_name = 'fooddecorator';
}

public function cook(){
return "cooking";
}
}

//青椒
class capsicum extends fooddecorator
{
public $_food;
public function __construct($food)
{
$this->_name = 'capsicum';
if($food instanceof food)
{
$this->_food = $food;
}else{
return false;
}
}

public function cook()
{
return $this->_food->cook()." cooked_capsicum";
}
}

//肉丝
class meat extends fooddecorator
{
public $_food;
public function __construct($food)
{
$this->_name = 'meat';
if($food instanceof food)
{
$this->_food = $food;
}else{
return false;
}
}

public function cook()
{
return $this->_food->cook()." cooked_meat";
}
}

//qr 青椒加饭 qjrs means 青椒肉丝
$rice = new rice();
//加青椒
$qr = new capsicum($rice);
//加肉
$qjrs = new meat($qr);

echo "fried green peppers:".$qjrs->cook();
?>

结果:

好像忘记加盐了0.0
装饰模式是围绕一个核心,然后动态装饰这个核心,很明显盖浇饭的核心是饭,在饭上加不同的菜,产生了不同的盖浇饭
这个时候估计有人说了,我不用装饰模式也可以实现着个过程啊

然后写了这样的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
abstract class food
{
public $_name;
abstract public function cook();
}

class rice extends food
{
public function __construct()
{
$this->_name = 'rice';
}

public function cook()
{
return " cooked_rice";
}
}

class capsicum extends food
{
public function __construct()
{
$this->_name = 'capsicum';
}

public function cook()
{
return " cooked_capsicum";
}
}

class meat extends food
{
public function __construct()
{
$this->_name = 'meat';
}

public function cook()
{
return " cooked_meat";
}
}

$rice = new rice();
$capsicum = new capsicum();
$meat = new meat();
echo "fried green peppers:".$rice->cook().$capsicum->cook().$meat->cook();
?>

结果很明显跟上面一样但是没有区别吗很明显第二种方法,第二种方法暴露了你做盖浇饭的顺序,就相当于顾客悄悄溜进厨房,看着厨师把盖浇饭做好了,见证了这一从无到有的过程,因此我们需要用装饰模式,将这加工处理的工程隐藏起来,只有这一个区别吗?很明显并不是,第二种方法三个子类处于同级,不分主次,但是不要忘了,顾客是去吃米饭的,之所以要了盖浇饭是为了让米饭更好吃,如果真的没有菜,做不成盖浇饭,只吃米顾客还是可以接受的,但是要是没有米,光有菜可不行,米饭是前提条件。要是觉得难以接受这个设定,就把盖浇饭换成各种类型的粥吧,绿豆粥,红薯粥。。。,要是少了米,还能叫粥吗。

最后做下简单的总结

装饰模式总结

1.装饰模式是向原有的类,动态的添加新的功能。
2.把类中的装饰功能从类中移去,是简化了原有类。
3.跟继承的区别,装饰模式是围绕着一个核心,在该核心存在的情况下去进行的,存在主次的关系,而继承所有子类处于同级
4.装饰模式的装饰顺序也是很重要,继承则不存在这种问题。比如说,穿衣服,你应该先穿内衣,再穿外套,而不是任意顺序。
5.多用组合,少用继承

简单工厂模式定义

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现

简单工厂的 UML 图

简单工厂模式中的各个角色以及相应职责:

  1. 简单工厂: 简单工厂模式的核心,由它负责创建所有的所有类的内部逻辑.即通过调用简单工厂的类方法并传递参数,然后由简单工厂创建对应的类
  2. 抽象产品: 简单工厂模式所创建的所有对象的父类,这里父类不一定非要接口,也可以使抽象类,它负责描述所有实例所共有的公共接口
  3. 具体产品:简单工厂所创建的具体实例对象,这些具体的产品往往都拥有共同的父类

具体实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public interface Operation{
/*
* 获取结果
*/
public function get();
}

/*
* 加法类
*/
class OperationAdd implements Operation{
private $_NumA;
private $_NumB;

public function __construct($num1,$num2) {
$this->_NumA = $num1;
$this->_NumB = $num2;
}

public function get() {
return ($this->_NumA + $this->_NumB);
}
}

class OperationSub implments Operation {
private $_NumA;
private $_NumB;

public function __construct($num1,$num2) {
$this->_NumA = $num1;
$this->_NumB = $num2;
}

public function get() {
return ($this->_NumA - $this->_NumB);
}

}

public class OperaFactory{

private $_results;
private $_opera;

public function __construct() {
$this->_results = 0;
}

public function Calculate($num1,$num2,$operator) {
swtich($operator) {
case '+':
$this->_opera = new OperationAdd($num1,$num2);
break;
case '-':
$this->_opera = new OperationSub($num1,$num2);
break;
default:
break;
}
$this->_results = $this->_opera->get();
return $this->_results;
}
}

优缺点

在讲述优缺点的之前,我们可以先思考一个问题,就当前的例子而言,如果我们需要添加一个 乘法的类,我们只需要定义一个类方法继承Operation这个接口,然后实现该方法,最后在OperaFactory中的Calculate中加一个新的分支
优点:
从上述例子以及简单的思考,不难看出通过简单工厂设计模式使得程序变得更加灵活,便于修改,并易于复用,降低了代码的耦合性
缺点:
如我们在代码所见那样,所有的创建逻辑都在OperaFactory中的Calculate,一旦其不能正常工作,整个系统都将收到影响

一个上下文相关的分享提供者

layout

ViewPager

ViewPage是Android拓展包v4包中的类,可以让用户左右切换当前的View,官方api的描述如下:

Layout manager that allows the user to flip left and right through pages of data. You supply an implementation of a PagerAdapter to generate the pages that the view shows.
ViewPager is most often used in conjunction with Fragment, which is a convenient way to supply and manage the lifecycle of each page. There are standard adapters implemented for using fragments with the ViewPager, which cover the most common use cases. These are FragmentPagerAdapter and FragmentStatePagerAdapter; each of these classes have simple code showing how to build a full user interface with them.

从这个描述中我们可以知道以下几点:

  1. ViewPager绝大多数情况下和Frament结合使用,并且提供了FragmentPagerAdapter 和 FragmentStatePagerAdapter
  2. ViewPager需要配合PagerAdaper使用,PagerAdapter的作用是产生展示view的页面

TextView

1
android:textAppearance="?android:textAppearanceMedium"

这是设置文字的外观,引用系统自带的一个外观, ? 表示系统是否有这种外观,否则使用默认的外观

1
android:lineSpacingMultiplier="1.1"

设置行间距的倍数

1
android:lineSpacingExtra = "7dp"

设置行间距

ImageView

1
2
3
4
5
6
7
8
android:scaleType="fitCenter" //使用 CENTER 方式缩放图像
android:scaleType="center" //在视图中使图像居中,不执行缩放
android:scaleType="centerCrop" //均衡的缩放图像(保持图像原始比例),使图片的两个坐标(宽、高)都大于等于 相应的视图坐标(负的内边距).图像则位于视图的中央
android:scaleType="centerInside" //均衡的缩放图像(保持图像原始比例),使图片的两个坐标(宽、高)都小于等于 相应的视图坐标(负的内边距)
android:scaleType="fitEnd" //使用 END 方式缩放图像
android:scaleType="fitStart" //使用 START 方式缩放图像
android:scaleType="fitXY" //使用 FILL 方式缩放图像
android:scaleType="matrix" //绘制时,使用图像矩阵方式缩放

这是将图片边界缩放,以适应视图边界时的可选项.可参阅
ImageView.ScaleType代码演示

MainActivity

setOnPageChangeListener

第68行:ViewPager的setOnPageChangeListener弃用
setOnPageChangeListener 改为 addOnpageChangeListener
具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* Set a listener that will be invoked whenever the page changes or is incrementally
* scrolled. See OnPageChangeListener.
*
* @param listener Listener to set
*
* @deprecated Use addOnPageChangeListener(OnPageChangeListener)
* and removeOnPageChangeListener(OnPageChangeListener) instead.
*/
@Deprecated
public void setOnPageChangeListener(OnPageChangeListener listener) {
mOnPageChangeListener = listener;
}

其含义就是设置一个监听器用来监控页面改变或者递增的滚动.

OnPageChangeListener

OnPageChangeListener是一个接口,需要去自行实现
具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* Callback interface for responding to changing state of the selected page.
*/
public interface OnPageChangeListener {

/**
* This method will be invoked when the current page is scrolled, either as part
* of a programmatically initiated smooth scroll or a user initiated touch scroll.
*
* @param position Position index of the first page currently being displayed.
* Page position+1 will be visible if positionOffset is nonzero.
* @param positionOffset Value from [0, 1) indicating the offset from the page at position.
* @param positionOffsetPixels Value in pixels indicating the offset from position.
*/
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);

/**
* This method will be invoked when a new page becomes selected. Animation is not
* necessarily complete.
*
* @param position Position index of the new selected page.
*/
public void onPageSelected(int position);

/**
* Called when the scroll state changes. Useful for discovering when the user
* begins dragging, when the pager is automatically settling to the current page,
* or when it is fully stopped/idle.
*
* @param state The new scroll state.
* @see ViewPager#SCROLL_STATE_IDLE
* @see ViewPager#SCROLL_STATE_DRAGGING
* @see ViewPager#SCROLL_STATE_SETTLING
*/
public void onPageScrollStateChanged(int state);
}

从源码可以看出该接口是当选中页面状态改变时做出响应的,需要实现依次三个方法,三个方法分别对应着onPageScrolled(int position, float positionOffset, int positionOffsetPixels)(当页面滚动的时候),onPageSelected(int position)(当页面被选的时候),onPageScrollStateChanged(int state)(当页面滚动状态改变的时候)

PagerAdapter

官方api的说明:

Base class providing the adapter to populate pages inside of a ViewPager.You will most likely want to use a more
specific implementation of this, such as android.support.v4.app.FragmentPagerAdapter or
android.support.v4.app.FragmentStatePagerAdapter.

大致意思就是提供一个填充ViewPager中的页面内容的适配器.然后可能使用FragmentPagerAdapter和FragmentStatePagerAdapter可能性更高.

当继承PageAdapter的是否,需要重写以下的方法:

  1. instantiateItem(ViewGroup, int)
  2. destroyItem(ViewGroup, int, Object)
  3. getCount()
  4. isViewFromObject(View, Object)

具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* Create the page for the given position. The adapter is responsible
* for adding the view to the container given here, although it only
* must ensure this is done by the time it returns from finishUpdate(ViewGroup).
*
* @param container The containing View in which the page will be shown.
* @param position The page position to be instantiated.
* @return Returns an Object representing the new page. This does not
* need to be a View, but can be some other container of the page.
*
* @deprecated Use instantiateItem(ViewGroup, int)
*/
@Deprecated
public Object instantiateItem(View container, int position) {
throw new UnsupportedOperationException(
"Required method instantiateItem was not overridden");
}

/**
* Remove a page for the given position. The adapter is responsible
* for removing the view from its container, although it only must ensure
* this is done by the time it returns from finishUpdate(View).
*
* @param container The containing View from which the page will be removed.
* @param position The page position to be removed.
* @param object The same object that was returned by
* instantiateItem(View, int).
*
* @deprecated Use destroyItem(ViewGroup, int, Object)
*/
@Deprecated
public void destroyItem(View container, int position, Object object) {
throw new UnsupportedOperationException("Required method destroyItem was not overridden");
}

/**
* Return the number of views available.
*/
public abstract int getCount();

/**
* Determines whether a page View is associated with a specific key object
* as returned by instantiateItem(ViewGroup, int). This method is
* required for a PagerAdapter to function properly.
*
* @param view Page View to check for association with object
* @param object Object to check for association with view
* @return true if view is associated with the key object object
*/
public abstract boolean isViewFromObject(View view, Object object);

根据源码说的注释说明,可以得知:

  1. **instantiateItem(View container, int position)*该方法是在指定位置创建相应的页面,其中参数container*是展示页面中的view,参数position页面被实例化的位置,不过该方法现在已经被弃用,改用为instantiateItem(ViewGroup container, int position)
  2. **destroyItem(View container, int position, Object object)*该方法是移除指定位置的页面,其中参数container*是将要被移走页面的view,参数position是将要被移除页面的位置,参数object是由instantiateItem(View, int)返回的对象,该方法也被弃用,改用为destroyItem(ViewGroup, int, Object)
  3. **getCount()**该方法这是返回可以获取到的view数量
  4. isViewFromObject(View view, Object object) 判断当前view跟由instantiateItem(ViewGroup, int)返回的对象是否有关联,如果有则返回true,参数view需要校验的view,参数object需要校验的对象

LayoutInflater

layoutInflater其作用类似findViewById(),不同点则是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等).
具体作用:

  1. 对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入
  2. 对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获得其中的界面元素

LayoutInflater 是一个抽象类,在文档中如下声明:

1
public abstract class LayoutInflater extends Object

获得 LayoutInflater 实例的三种方式:

  1. LayoutInflater inflater = getLayoutInflater(); //调用Activity的getLayoutInflater()
  2. LayoutInflater inflater = LayoutInflater.from(context);
  3. LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

LayoutInflater的inflate方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public View inflate(int resource, ViewGroup root) {
throw new RuntimeException("Stub!");
}

public View inflate(XmlPullParser parser, ViewGroup root) {
throw new RuntimeException("Stub!");
}

public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
throw new RuntimeException("Stub!");
}

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
throw new RuntimeException("Stub!");
}

其返回值均为view,但是值得注意的是:inflater 是用来找 res/layout 下的 xml 布局文件,并且实例化;findViewById() 是找具体 xml 布局文件中的具体 widget 控件(如:Button、TextView 等

ShareActionProvider

官网api说明:

Provides a share action, which is suitable for an activity’s app bar. Creates views that enable data sharing. If the provider appears in the overflow menu, it creates a submenu with the appropriate sharing actions.

从上述描述我们可以ShareActionProvider其实会提供一个分享的按钮.如果分享按钮出现在溢出菜单,它会创建一个合适的子菜单

onCreateOptionsMenu

1
2
3
public boolean onCreateOptionsMenu(Menu menu) {
throw new RuntimeException("Stub!");
}

此方法用于初始化菜单,其中menu参数就是即将要显示的Menu实例.返回true则显示该menu,false 则不显示,只会在第一次初始化菜单时调用.


Activity菜单机制
Activity有一套机制来实现对菜单的管理,方法如下:

  1. public boolean onCreateOptionsMenu(Menu menu)
  2. public boolean onPrepareOptionsMenu(Menu menu) 在onCreateOptionsMenu执行后,菜单被显示前调用;如果菜单已经被创建,则在菜单显示前被调用.同样的,返回true则显示该menu,false 则不显示;(可以通过此方法动态的改变菜单的状态,比如加载不同的菜单等)
  3. public void onOptionsMenuClosed(Menu menu) 每次菜单被关闭时调用.(菜单被关闭有三种情形,menu按钮被再次点击,back按钮被点击或者用户选择了某一个菜单项)
  4. public boolean onOptionsItemSelected(MenuItem item) 菜单项被点击时调用,也就是菜单项的监听方法