2015年11月8日星期日

Android开发自学笔记(Android Studio)—4.4 AdapterView及其子类 - 牧 童

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
Android开发自学笔记(Android Studio)―4.4 AdapterView及其子类 - 牧 童  阅读原文»

一、引言

AdapterView本身是一个抽象类,而它派生的子类在用法上也基本相似,只是在显示上有一定区别,因此把他们也归为一类。

AdapterView具有如下特征:

  1. AdapterView继承自ViewGroup,本质是个容器
  2. AdapterView可以包含多个"列表项",并将这多个列表项以合适的形式展示。
  3. AdapterView显示的多个列表项的内容由Adapter提供

AdapterView及其子类的继承关系如下图所示:

image

由于Gallery是一个过时的API,Android推荐使用HorizontalScrollView来替代,所以我也不再对它进行学习。

而由AdapterView直接派生的三个类:AbsListView、AbsSpinner、AdapterViewAnimator也都是抽象类,所以我们用的最多的也就是图中第四行及以下的子类。

二、ListView

ListView就是我们所说的列表视图,也是我们最常用的一个组件,它是以垂直列表的形式展示所有数据项,而生成列表视图的方式主要有两种:

  1. 直接用ListView进行创建
  2. 让Activity继承ListActivity

而一旦获取到ListView后,对数据的填充就是由Adapter提供内容了,通常使用setAdapter方法。

ListView、GridView、Spinner等AdapterView都只是容器,而Apdater负责提供容器的内容。

AdapterView则负责采用合适的方式显示Adapter提供的内容。

AbsListView的常用属性和相关方法见下表:

属性

相关方法

说明

android:choiceMode

设置AbsListView的选择方式:
none:不显示任何选中项

singleChoice:允许单选

multipleChoice:允许多选

multipleChoiceModal:允许多选

android:drawSelectorOnTop setDrawSelectorOnTop(boolean) 如果该属性设置为true,选中的列表项将会显示在上面
android:fastScrollEnabled 设置是否允许快速滚动。如果该属性设置为true,将会显示滚动图标,并允许用户拖动该滚动图标进行快速滚动。
android:listSelector setSelector(int) 指定被选中的列表项上绘制的Drawable
android:scrollingCache 如果设置为true,则在滚动时将会使用缓存
android:smoothScrollbar setSmoothScrollbarEnabled(boolean) 如果设置为false,则不在header View之后绘制分隔条
android:stackFromBottom 设置是否从底端开始排列列表项
android:textFilterEnabled 设置是否对列表项进行过滤。只有当该AdapterView对应的Adapter实现了Filter接口时该属性才会作用。
android:transcriptMode 设置组件的滚动模式:
disabled:关闭滚动(默认)
normal:当该AbsListView收到数据改变通知,且最后一个列表项可见时,该AbsListView将会滚动到底端。
alwaysScroll:该AbsListView总会自动滚动到底端

ListView提供的属性如下表:

属性

说明

android:divider 设置List列表项的分隔条(可用颜色分隔,也可用drawable对象分隔)
android:dividerHeiht 设置分隔条的高度
android:entries 指定一个数组资源,Android将根据该数组资源来生成ListView
android:footerDividerEnabled 如果设置成false,则不在footer View之前绘制分隔条
andorid:headerDividerEnabled 如果设置成false,则不再header View之前绘制分隔条

示例代码及显示效果图如下:

image

示例布局中只定义了一个ListView,并通过android:entries指定了数据源,通过android:divider指定了红色的分隔条。

数据源位于value/arrays.xml中,代码如下:

image

使用数组作为数据源十分简单,但是局限性也很大,能定制的内容也非常少,甚至字号大小,颜色都不能改变。

如果想对ListView的外观、行为进行定制,就需要把ListView作为AdapterView使用,通过Adapter控制列表项的显示和交互。

三、Adapter接口及其实现类

Adapter本身是一个接口,它派生了ListAdapter和SpinnerAdapter两个子接口,其中ListAdapter为AbsAdapter提供列表项,而SpinnerAdapter为AbsSpinner提供列表项。Adapter及其实现类的继承关系如下图所示:

image

其中ArrayAdapter、SimpleAdapter、SimpleCursorAdapter、BaseAdapter都是常用的实现类。

1.ArrayAdapter:简单、易用的Adapter,通常用于将数组或者List集合的多个值包装为列表项的数据源

2.SimpleAdapter:功能强大的Adapter,可用于将List集合的多个对象包装为列表项的数据源

3.SimpleCursorAdapter:与SimpleAdapter类似,只是用于包装Cursor提供的数据

4.BaseAdapter:通用用于被扩展。扩展BaseAdapter可以对各个列表项进行最大程度的定制。

3.1 ArrayAdapter

布局页和示意图如下:

image

布局中只有一个ListView,设置了分隔条为红色。看一下后台代码:

OC基础--简单单例 - S了个J  阅读原文»

什么是单例

什么是单例模式:(Singleton)

单例模式的意图是是的类的对象成为系统中唯一的实例,供一个访问点,供客户类 共享资源

单例的使用场景

1.类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法

2.这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码

单例设计模式的要点:

1. 某个类只能有一个实例。

2.他必须自行创建这个对象

3.必须自行向整个系统供这个实例;

4.为了保证实例的唯一性,我们必须将

5.这个方法必须是一个静态类

代码实现:

Tools.h

//
// Person.h
// 练习2
//
// Created by king on 15/11/8.
// Copyright © 2015年 king. All rights reserved.
//
/*


创建一个person的单利对象。使用alloc,copy创建的时候时候只会产生一个对象,并且提供一个单利接入的方法(shareInstance)。
*/
#import <Foundation/Foundation.h>
// 遵守copy协议
@interface Tools : NSObject <NSCopying, NSMutableCopying>

// 一般情况下创建一个单例对象都有一个与之对应的类方法
// 一般情况下用于创建单例对象的方法名称都以share开头, 或者以default开头
+ (instancetype)shareInstance;
@end

Tools.m

#import "Tools.h"

@implementation Tools

+(instancetype)shareInstance {

Tools
*instance = [[self alloc] init];
return instance;
}
// 定义一个全局变量
static Tools *_instance = nil;
+(instancetype)allocWithZone:(struct _NSZone *)zone {
/*
// 当前代码在多线程是可能会出现问题
if (_instance == nil) {
// 由于 alloc new copy mutableCopy 创建对象都会调用这个方法
// 所有我们只需要这里控制当前对象只创建一次
_instance = [[super allocWithZone:zone] init];
}
return _instance;
*/

// 当前代码在多线程也能用
static dispatch_once_t onceToken;
dispatch_once(
&onceToken, ^{
_instance
= [[super allocWithZone:zone] init];
});
return _instance;
}

- (id)copyWithZone:(NSZone *)zone {

return _instance;
}

- (id)mutableCopyWithZone:(NSZone *)zone {

return _instance;
}


@end

而在MRC中 如果调用 release 会发生运行时错误

所以我们需要从写 release retain retainCount

// MRC中
- (oneway void)release {
// 因为只会创建一次 所以我们不能释放当前对象
// 所有这里什么都不做
}
- (instancetype)retain {

return _instance;
}
- (NSUInteger)retainCount {


// 为了程序员之间方便交流 我们一般不写 1
// 而是写一个较大的值,让人一看就知道,这个对象时单例
// return 1;
return MAXFLOAT;
}

利用宏抽取优化代码

Singleton.h

// 以后就可以使用interfaceSingleton来替代后面的方法声明
#define interfaceSingleton(name) +(instancetype)share##name


#if __has_feature(objc_arc)
// ARC
#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name
*instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(
&onceToken, ^{ \
_instance
= [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}
#else
// MRC

#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name
*instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(
&onceToken, ^{ \
_instance
= [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instanc

阅读更多内容

没有评论:

发表评论