yii框架AR详解

yii框架AR详解

  虽 然Yii DAO可以处理事实上任何数据库相关的任务,但很可能我们会花费90%的时间用来编写一些通用的SQL语句来执行CRUD操作(创建,读取,更新和删除)。 同时我们也很难维护这些PHP和SQL语句混合的代码,要解决这些问题,我们可以使用Active Record。
    Active Record(AR)是一种流行的对象关系映射(ORM)技术。每个AR类代表一个数据表(或视图),其字段作为AR类的属性,一个AR实例代表在表中的 一行。常见的CRUD操作被作为AR类的方法执行。 于是,我们可以使用更面向对象的方法处理我们的数据。例如,我们可以使用下面的代码在
    tbl_post
    表中插入一个新行:
    $post=new Post;
    $post->title=‘sample post‘;
    $post->content=‘post body content‘;
    $post->save();在下面我们将介绍如何设置AR和用它来执行CRUD操作。在下一小节我们将展示如何使用AR 处理数据库中的关系。为了简单起见,我们使用本节下面的数据库表作为例子。 请注意,如果你使用MySQL数据库,在下面的SQL中您应该替换
    AUTOINCREMENT
    为
    AUTO_INCREMENT
    。
    CREATE TABLE tbl_post (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    title VARCHAR(128) NOT NULL,
    content TEXT NOT NULL,
    create_time INTEGER NOT NULL
    );注意: AR不是要解决所有与数据库相关的任务。它最好用于在PHP结构中模型化数据表和执行不复杂的 SQL 语句。 而 Yii DAO 应该用于复杂的情况下。
    建立数据库连接
    AR需要一个数据库连接以执行数据库相关的操作。默认情况下,应用中的db组件提供了 CDbConnection实例作为我们需要的数据库连接。

下面的应用程序配置提供了一个例子:
    return array(
    ‘components‘=>array(
    ‘db‘=>array(
    ‘class‘=>‘system.db.CDbConnection‘,
    ‘connectionString‘=>‘sqlite:path/to/dbfile‘,
    // turn on schema caching to improve performance
    // ‘schemaCachingDuration‘=>3600,
    ),
    ),
    );

提示: 由于Active Record需要表的元数据来确定数据表的字段信息, 这需要时间来读取和分析元数据。如果您的数据库结构是比较固定的,你应该打开缓存。 打开方法是配置CDbConnection::schemaCachingDuration属 性为一个大于0的值。

附mysql连接方式

‘db‘=>array(//---------------------------------------------------------------DB CONNECT            ‘connectionString‘=>‘mysql:host=‘.DB_HOST.‘;dbname=‘.DB_NAME.";port=".DB_PORT.";unix_socket=".DB_SOCK,  ‘username‘=>DB_USERNAME, ‘password‘=>DB_PASSWORD, ‘charset‘ =>‘utf8‘,       ),
    AR的支持受限于数据库管理系统。目前,只有以下数据库管理系统支持:
    MySQL 4.1 或以后版本
    PostgreSQL 7.3 或以后版本
    SQLite 2 和 3
    Microsoft SQL Server 2000 或以后版本
    Oracle
    注意: Microsoft SQL Server自1.0.4版本提供支持;而对 Oracle 自1.0.5版本即提供支持。
    如果你想使用其他组件而不是
    db,或者你使用 AR 访问多个数据库,你应该重写CActiveRecord::getDbConnection()。 CActiveRecord类 是所有AR类的基类。
    提示: 有两种方法可以在AR模式下使用多种数据库系统。如果数据库的模式不同, 您可以以不同的getDbConnection()来 创建不同的 AR 类。否则,动态改变静态变量CActiveRecord::db 是一个更好的主意。
    定义 AR 类
    为了使用一个数据表,我们首先需要扩展CActiveRecord来 定义一个AR类。 每个AR类代表一个数据库表,每个AR实例代表数据表中的一行。下面的代码介绍了 要创建一个对应
    tbl_post
    表的AR类所需要的最少的代码。
    class Post extends CActiveRecord
    {
    public static function model($className=__CLASS__)
    {
    return parent::model($className);
    }
    public function tableName()
    {
    return ’tbl_post’;
    }
    }

提示: 因为AR类在很多地方被引用,我们可以导入包含AR类的整个目录,而不是逐个引入它们。例如,若我们所有的AR类文件位于 protected/models,我们可以如下配置:
    return array(
    ’import’=>array(
    ’application.models.*’,
    ),
    );
    默认的, AR 类的名字和数据表的名字相同。 若它们不同需要重写 tableName()方法。 方法 model() is declared as such for every AR class (to be explained shortly)。
    信息: 要使用版本 1.1.0 引入的表前缀特征, AR 的方法 tableName() 可以被如下重写,
    public function tableName()
    {
    return ’{{post}}’;
    }这样,不是返回一个完整的表名, 我们返回去掉了前缀的表名,并把它环绕在双弯曲括号中。
    一条数据的字段可以作为相应 AR 实例的属性被访问。 例如, 下面的代码设置了 title 字段(属性):
    $post=new Post;
    $post->title=’a sample post’;虽然我们没有在 Post 类中明确声明 title 属性, 我们仍然可以在上面的代码中访问它。 这是因为 title 是表 tbl_post 中的字段, 在 PHP__get() 魔术方法的帮助下,CActiveRecord 可以将其作为一个属性来访问。 若以同样方式尝试访问不存在的字段,一个异常将被抛出。
    信息:在此指南中,我们为所有的数据表和字段采取小写格式。这是因为在不同的DBMS中,对于大小写的敏感是不 同的。例如,PostgreSQL默认对字段名字是大小写不敏感的, and we must quote a column in a query condition if the column contains mixed-case letters.使用小写格式可以避免此问题。
    AR 依赖于数据表良好定义的主键。 若一个表没有一个主键, 需要相应的 AR 类指定哪些字段应当为主键,通过重写
    primaryKey()
    方法,
    public function primaryKey()
    {
    return ’id’;
    // For composite primary key, return an array like the following
    // return array(’pk1’, ’pk2’);
    }创建记录
    要插入新的一行记录到数据表中, 我们创建一个新的对应的 AR 类实例, 设置和字段对应的属性的值, 并调用 save() 方法来完成插入。
    $post=new Post;
    $post->title=’sample post’;
    $post->content=’content for the sample post’;
    $post->create time=time();
    $post->save();若表的主键是自增的, 在插入后 AR 实例将包含一个更新后的主键。 在上面的例子中, 属性id 将映射为新插入的主键值, 即使我们没有明确更改它。
    若在表模式中,一个字段被定义为一些静态默认值(static default value) (例如一个字符串, 一个数字), 在这个AR实例被创建后, 实例中相应的属性将自动有相应的默认值。 改变此默认值的一个方式是在 AR 类中明确声明此属性:
    class Post extends CActiveRecord
    {
    public $title=’please enter a title’;
    ……
    }
    $post=new Post;
    echo $post->title;  // this would display: please enter a title从版本 1.0.2 开始, 在记录被保存前(插入或更新)一个属性可以赋值为 CDbExpression 类型的值。 例如, 为了保存由 MySQL NOW() 函数返回的时间戳, 我们可以使用下面的代码:
    $post=new Post;
    $post->createtime=new CDbExpression(’NOW()’);
    // $post->create time=’NOW()’; will not work because
    // ’NOW()’ will be treated as a string
    $post->save();

提示:AR 允许我们执行数据库操作而无需编写麻烦的 SQL 语句, 我们常常想要知道什么 SQL 语句被 AR 在下面执行了。 这可以通过打开 Yii 的记录(logging)特征来实现。 例如, 我们可以在应用配置中打开 CWebLogRoute , 我们将看到被执行的 SQL 语句被显示在每个页面的底部。 自版本 1.0.5 开始, 我们可以在应用配置设置 CDbConnection::enableParamLogging 为 true 以便 绑定到 SQL 语句的参数值也被记录。
    读取记录
    要读取数据表中的数据,我们可以调用下面其中一个
    find
    方法:
    // find the first row satisfying the specified condition
    $post=Post::model()->find($condition,$params);
    // find the row with the specified primary key
    $post=Post::model()->findByPk($postID,$condition,$params);
    // find the row with the specified attribute values
    $post=Post::model()->findByAttributes($attributes,$condition,$params);
    // find the first row using the specified SQL statement
    $post=Post::model()->findBySql($sql,$params);在上面, 我们使用
    Post::model()
    调用
    find
    方法。 记得静态方法
    model()
    是每个 AR 类所必需的。 此方法返回一个 AR 实例,此实例 被用来访问类水平的方法(类似于静态的类方法)。
    若
    find
    方法找到一行记录满足查询条件, 它将返回一个 Post 实例,此实例的属性包含表记录对应的字段值。 然后我们可以读取被载入的值如同我们访问普通对象的属性, 例如,
    echo $post->title;
    .
    find
    方法将返回 null 若在数据库中没有找到满足条件的记录。
    当调用 find,我们使用$condition 和 $params 来指定查询条件。 这里 $condition 可以是字符串代表一个 SQL 语句中的 WHERE 子语句,$params 是一个参数数组,其中的值应被绑定到$condition的占位符。例如,
    // find the row with postID=10
    $post=Post::model()->find(’postID=:postID’, array(’:postID’=>10));注意: 在上面的例子中, 对于某些 DBMS 我们可能需要转义对 postID 字段的引用。 例如, 若我们使用 PostgreSQL, 我们需要写condition 为 “postID”=:postID ,因为 PostgreSQL 默认情况下对待字段名字为大小写不敏感的。
    我们也可以使用  $condition 来指定更复杂的查询条件。 不使用字符串,我们让$condition

为一个 CDbCriteria 实例,可以让我们指定条件而不限于 WHERE 子语句。例如,

$criteria=new CDbCriteria;
    $criteria->select=’title’; // only select the ’title’ column
    $criteria->condition=’postID=:postID’;
    $criteria->params=array(’:postID’=>10);
    $post=Post::model()->find($criteria); // $params is not needed注意, 当使用 CDbCriteria 作为查询条件, 不再需要参数
    $params
    因为它可以在 CDbCriteria 中被指定, 如上所示。
    一个可选的 CDbCriteria 方式是传递一个数组到
    find
    方法。 数组的键和值分别对应于 criteria 的属性名字和值。上面的例子可以被如下重写,
    $post=Post::model()->find(array(
    ’select’=>’title’,
    ’condition’=>’postID=:postID’,
    ’params’=>array(’:postID’=>10),
    ));信息: 当一个查询条件是关于匹配一些字段用指定的值, 我们可以使用 findByAttributes()。 我们让参数$attributes为一个数组,数组的值由字段名字索引。 在一些框架中,此任务可以通过调用类似于
    findByNameAndTitle 的方法来实现。 虽然这个方法看起来很有吸引力, 但它常常引起混淆和冲突,例如字段名字的大小写敏感性问题。
    当多行记录满足指定的查询条件, 我们可以使用下面的
    findAll
    方法将它们聚合在一起, 每个都有它们自己的副本
    find
    方法。
    // find all rows satisfying the specified condition
    $posts=Post::model()->findAll($condition,$params);
    // find all rows with the specified primary keys
    $posts=Post::model()->findAllByPk($postIDs,$condition,$params);
    // find all rows with the specified attribute values
    $posts=Post::model()->findAllByAttributes($attributes,$condition,$params);
    // find all rows using the specified SQL statement
    $posts=Post::model()->findAllBySql($sql,$params);若没有符合条件的记录,
    findAll
    返回一个空数组。 不同于
    find
    方法,find方法会返回 null.
    除了上面所说的 find和findAll 方法, 为了方便, 下面的方法也可以使用:
    // get the number of rows satisfying the specified condition
    $n=Post::model()->count($condition,$params);
    // get the number of rows using the specified SQL statement
    $n=Post::model()->countBySql($sql,$params);
    // check if there is at least a row satisfying the specified condition
    $exists=Post::model()->exists($condition,$params);更新记录
    一个 AR 实例被字段值填充后, 我们可以改变它们并保存回它们到数据表中。
    $post=Post::model()->findByPk(10);
    $post->title=’new post title’;
    $post->save(); // save the change to database若我们所见, 我们使用相同的 save() 方法来执行插入和更新操作。 若一个 AR 实例被使用 new 操作符创建,调用 save() 将插入一行新记录到数据表中; 若此 AR 实例是一些find或findAll方法调用的结果, 调用 save() 将更新表中已存在的记录。 事实上, 我们可以使用 CActiveRecord::isNewRecord 来检查一个 AR 实例是否是新建的。
    更新一行或多行表中的记录而不预先载入它们也是可能的。 AR 提供如下方便的类水平的(class-level)方法来实现它:
    // update the rows matching the specified condition
    Post::model()->updateAll($attributes,$condition,$params);
    // update the rows matching the specified condition and primary key(s)
    Post::model()->updateByPk($pk,$attributes,$condition,$params);
    // update counter columns in the rows satisfying the specified conditions
    Post::model()->updateCounters($counters,$condition,$params);在上面,
    $attributes
    是一个值由字段名索引的数组;
    $counters
    是一个增加值由字段名索引的数组;
    $condition
    和
    $params
    已在之前被描述。
    删除记录
    我们也可以删除一行记录若一个 AR 实例已被此行记录填充。
    $post=Post::model()->findByPk(10); // assuming there is a post whose ID is 10
    $post->delete(); // delete the row from the database table注意, 在删除后, 此 AR 实例仍然未改变, 但相应的表记录已经不存在了。
    下面类水平的(class-level)方法被用来删除记录,而无需预先载入它们:
    // delete the rows matching the specified condition
    Post::model()->deleteAll($condition,$params);
    // delete the rows matching the specified condition and primary key(s)
    Post::model()->deleteByPk($pk,$condition,$params);数据验证
    当插入或更新一行记录, 我们常常需要检查字段的值是否符合指定的规则。 若字段值来自用户时这一点特别重要。通常我们永远不要信任用户提交的数据。
    AR 自动执行数据验证在 save() 被调用时。验证基于在 AR 类中的 rules()方 法中指定的规则。如何指定验证规则的更多信息, 参考 声明验证规则 部分。 下面是保存一条记录典型的工作流程:
    if($post->save())
    {
    // data is valid and is successfully inserted/updated
    }
    else
    {
    // data is invalid. call getErrors() to retrieve error messages
    }当插入或更新的数据被用户在 HTML 表单中提交, 我们需要赋值它们到对象的 AR 属性。 我们可以这样做:
    $post->title=$_POST[’title’];
    $post->content=$_POST[’content’];
    $post->save();若有很多字段, 我们可以看到一个很长的赋值列表。 可以使用下面的 attributes 属性来缓解。 更多细节可以在 Securing Attribute Assignments 部分和 Creating Action 部分找到。
    // assume $_POST[’Post’] is an array of column values indexed by column names
    $post->attributes=$_POST[’Post’];
    $post->save();对比记录
    类似于表记录, AR 实例由它们的主键值来被识别。 因此,要对比两个 AR 实例, 我们只需要对比它们的主键值, 假设它们属于相同的 AR 类。 然而,一个更简单的方式是调用 CActiveRecord::equals()。
    信息: 不同于 AR 在其他框架的执行, Yii 在其 AR 中支持多个主键。 一个复合主键由两个或更多字段构成。 对应的, 主键值在 Yii 中表示为一个数组。 The
    primaryKey
    属性给出一个 AR 实例的主键值。
    Customization
    CActiveRecord 提供了一些占位符(placeholder)方法可被用来在子类中重写以自定义它的工作流程。
    beforeValidate 和 afterValidate: 它们在验证执行 之前/后 被调用。
    beforeSave 和 afterSave: 它们在保存一个 AR 实例之前/后 被调用。
    beforeDelete 和 afterDelete: 它们在一个 AR 实例被删除 之前/后 被调用。
    afterConstruct: 这将在每个 AR 实例被使用 new 操作符创建之后被调用。
    beforeFind: 它在一个 AR finder 被用来执行一个查询之前被调用 (例如 find(), findAll())。 从版本 1.0.9 可用。
    afterFind: 它在每个 AR 实例被创建作为一个查询结果后被调用。
    在 AR 中使用事务处理
    每个 AR 实例包含一个名为 dbConnection 的属性,它是一个 CDbConnection 实例。 这样我们在使用 AR 时就可以使用 Yii DAO 提供的事务处理特征:
    $model=Post::model();
    $transaction=$model->dbConnection->beginTransaction();
    try
    {
    // find and save are two steps which may be intervened by another request
    // we therefore use a transaction to ensure consistency and integrity
    $post=$model->findByPk(10);
    $post->title=’new post title’;
    $post->save();
    $transaction->commit();
    }
    catch(Exception $e)
    {
    $transaction->rollBack();
    }命名空间(new!)
    注意: 对于命名空间的支持从版本 1.0.5 开始。 思路来源于 Ruby on Rails.
    a named scope represents a named query criteria that can be combined with other named scopes and applied to an active record query.
    命名空间被主要在 CActiveRecord::scopes() 方法中声明,格式是 name-criteria 对。 下面的代码在 Post 模型类中声明了两个命名空间,
    published
    和
    recently
    :
    class Post extends CActiveRecord
    {
    ……
    public function scopes()
    {
    return array(
    ’published’=>array(
    ’condition’=>’status=1’,
    ),
    ’recently’=>array(
    ’order’=>’create time DESC’,
    ’limit’=>5,
    ),
    );
    }
    }每个命名空间被声明为一个被用来初始化一个 CDbCriteria 实例的数组。例如,命名空间
    recently
    指定 了
    order
    属性为
    create_time DESC
    ,
    limit
    属性为 5, 翻译为一个查询条件就是应当返回最近发表的5篇帖子。
    命名空间大多数作为find方法的 modi?er 来使用。几个命名空间可以连接在一起,则样可以得到一个更加有限制性的查询结果集。 例如,要找到最近发表的帖子,我们可以使用下面的代码:
    $posts=Post::model()->published()->recently()->findAll();通常命名空间必须出现在一个 find 方法的左边。 Each of them provides a query criteria, which is combined with other criterias, including the one passed to the find method call. The net e?ect is like adding a list of ?lters to a query.
    从版本 1.0.6 开始, 命名空间也可以使用 update 和 delete 方法。例如,下面的代码将删除 所有最近发表的帖子:
    Post::model()->published()->recently()->delete();注意: 命名空间只可以被作为类水平的方法使用。也就是说,此方法必须使用 ClassName::model() 来调用它。
    参数化命名空间(Parameterized Named Scopes)
    命名空间可以被参数化。例如,我们想要定制命名空间
    recently
    指定的帖子数目。 要这样做,不是在 CActiveRecord::scopes 方法中声明命名空间,我们需要定义一个新的方法,它的名字和空间的名字相同:
    public function recently($limit=5)
    {
    $this->getDbCriteria()->mergeWith(array(
    ’order’=>’create time DESC’,
    ’limit’=>$limit,
    ));
    return $this;
    }然后,我们可以使用下面的语句来检索 3 个最近发表的帖子:
    $posts=Post::model()->published()->recently(3)->findAll();若我们不使用上面的参数 3 ,默认情况下我们将检索 5 个最近发表的内容。
    默认命名空间
    一个模型类可以有一个默认命名空间,它被应用于此模型所有的查询 (包括 relational ones)。例如,一个支持多种语言的网站只是以当前用户指定的语言来显示内容。 因为有很多关于站点内容的查询,我们可以定义一个默认命名空间来解决这个问题。要这样做,我们重写 CActiveRecord::defaultScope 方法如下,
    class Content extends CActiveRecord
    {
    public function defaultScope()
    {
    return array(
    ’condition’=>"language=’".Yii::app()->language."’",
    );
    }
    }现在,若调用下面的方法将自动使用上面定义的查询条件:
    $contents=Content::model()->findAll();注意默认命名空间只应用于 SELECT 查询。它忽视 INSERT,UPDATE 和 DELETE 查询。
    Popularity: unranked [?]

转自:http://www.cnblogs.com/siliconvalley/p/3259608.html

时间: 2024-10-24 16:17:21

yii框架AR详解的相关文章

测试框架mochajs详解

测试框架mochajs详解 章节目录 关于单元测试的想法 mocha单元测试框架简介 安装mocha 一个简单的例子 mocha支持的断言模块 同步代码测试 异步代码测试 promise代码测试 不建议使用箭头函数 钩子函数 钩子函数的描述参数 异步的钩子函数 全局钩子 延迟启动测试 测试用例TODO 仅执行一个用例集/用例 跳过哪些用例集/用例 重新执行用例 动态生成用例 测试时间 测试超时 用例集执行超时 用例执行超时 钩子函数超时 diff差异比较功能 mocha使用命令和参数 mocha

Java集合框架Koloboke详解

Java集合框架Koloboke详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs Koloboke的目标是替换标准的Java集合和流的API,提供更高效的实现.Koloboke目前的版本主要是替换java.util.HashSet和java.util.HashMap. Koloboke提供了一套完整的集合原始类型的实现,可以避免开销很大的装箱/拆箱操作,节省了原始类型装箱消耗的内存. 在Koloboke中,Has

yii之srbac详解

一.安装篇 1.下载http://www.yiiframework.com/extension/srbac/ 将解压得到的srbac文件夹放在moudles目录下. 2.在项目的主配置文件中mai.php: 'modules'=>array( // uncomment the following to enable the Gii tool 'gii'=>array( 'class'=>'system.gii.GiiModule', 'password'=>'123123', //

S2SH框架集成详解(Struts 2.3.16 + Spring 3.2.6 + Hibernate 3.6.10)

近期集成了一次较新版本的s2sh,出现了不少问题,网上资料也是良莠不齐,有的甚至就是扯淡,简单的把jar包扔进去就以为是集成成功了,在这里整理一下详细的步骤,若哪位有什么不同看法,可以留言,欢迎批评改正. 首先说下集成的环境,Eclipse 4.4,Tomcat 7.0.54,Struts2.3.16,Hibernate3.6.10,Spring3.2.6 相关JAR包已上传至百度云:http://pan.baidu.com/s/1pJluA5l 搭建Struts2框架 1. 创建Java We

Hadoop新MapReduce框架Yarn详解

简介 本文介绍了Hadoop自0.23.0版本后新的MapReduce框架(Yarn)原理,优势,运行机制和配置方法等,着重介绍新的yarn框架相对于原框架的差异及改进,并通过Demo示例详细介绍了在新的Yarn框架下搭建和开发Hadoop程序的方法.读者通过本文中新旧Hadoop MapReduce框架的对比,更深刻理解新的yarn框架技术与那里和设计思想,文中的Demo代码经过微小修改既可用于用户基于Hadoop新框架的实际生产环境. Hadoop MapReduceV2(Yarn)框架简介

Hadoop 新 MapReduce 框架 Yarn 详解

原 Hadoop MapReduce 框架的问题 对于业界的大数据存储及分布式处理系统来说,Hadoop 是耳熟能详的卓越开源分布式文件存储及处理框架,对于 Hadoop 框架的介绍在此不再累述,读者可参考 Hadoop 官方简介.使用和学习过老 Hadoop 框架(0.20.0 及之前版本)的同仁应该很熟悉如下的原 MapReduce 框架图: 图 1.Hadoop 原 MapReduce 架构 从上图中可以清楚的看出原 MapReduce 程序的流程及设计思路: 首先用户程序 (JobCli

Spring基于注解TestContext 测试框架使用详解

概述 Spring 2.5 相比于 Spring 2.0 所新增的最重要的功能可以归结为以下 3 点: 1.基于注解的 IoC 功能:  2.基于注解驱动的 Spring MVC 功能:  3.基于注解的 TestContext 测试框架. Spring 推荐开发者使用新的基于注解的 TestContext 测试框架,本文我们将对此进行详细的讲述. 低版本的 Spring 所提供的 Spring 测试框架构在 JUnit 3.8 基础上扩展而来,它提供了若干个测试基类.而 Spring 2.5

Android开源框架Universal-Image-Loader详解

如果说评价一下哪个图片开源库最被广泛使用的话,我想应该可以说是Universal-Image-Loader,在主流的应用中如 果你随便去反编译几个,基本都能看到他的身影,它就像个图片加载守护者,默默的守护着图片加载.相信很多人对 这个异步加载图片框架还不是很熟,再加上最近它更改优化了好几个地方,而网上的大部分资料还是以前的,于是花 了几天时间专门的研究了下开源框架Universal-Image-Loader(实际上是近期项目刚好用到,且仔细的考虑过各种情 况),希望对新手能有所帮助,也希望大神能

Android开源框架Image-Loader详解

如果说评价一下哪个图片开源库最被广泛使用的话,我想应该可以说是Universal-Image-Loader,在主流的应用中如 果你随便去反编译几个,基本都能看到他的身影,它就像个图片加载守护者,默默的守护着图片加载.相信很多人对 这个异步加载图片框架还不是很熟,再加上最近它更改优化了好几个地方,而网上的大部分资料还是以前的,于是花 了几天时间专门的研究了下开源框架Universal-Image-Loader(实际上是近期项目刚好用到,且仔细的考虑过各种情 况),希望对新手能有所帮助,也希望大神能