[转载]android开发我的新浪微博客户端-阅读微博UI篇(6.1)

mikel阅读(835)

[转载]android开发我的新浪微博客户端-阅读微博UI篇(6.1) – 遇见未知的自己 – 博客园.

上一篇完成了微博列表的功能,本篇接着做预读微博的功能,本篇主要讲讲UI部分的实现,最终实现的效果如上图所示。整个显示页面从上往下分为四部分,第一部分顶部工具条、第二部分作者头像和名称、第三部分微博正文、第四部分功能按钮区。

新建名为ViewActivity.java作为阅读微博的页面,再res/layout目录下新建名为view.xml的Layout,代码如下:

代码

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout
xmlns:Android=”http://schemas.Android.com/apk/res/android”
android:id
=”@+id/layout”
android:orientation
=”vertical”
android:layout_width
=”fill_parent”
android:layout_height
=”fill_parent”>
<RelativeLayout
android:layout_width=”fill_parent”
android:layout_height
=”wrap_content”
android:layout_margin
=”3px”>
<ImageView
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:src
=”@drawable/logo_ss”>
</ImageView>
<TextView
android:id=”@+id/showName”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_centerInParent
=”true”
android:textColor
=”#343434″
android:text
=”阅读微博”
android:textSize
=”16px”>
</TextView>
<ImageButton
android:id=”@+id/returnBtn”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_toLeftOf
=”@+id/homeBtn”
android:background
=”@drawable/bnt_return_selector”>
</ImageButton>
<ImageButton
android:id=”@+id/homeBtn”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_alignParentRight
=”true”
android:layout_marginLeft
=”12px”
android:background
=”@drawable/btn_home_selector”>
</ImageButton>
</RelativeLayout>
<LinearLayout
android:layout_width=”fill_parent”
android:layout_height
=”wrap_content”
android:background
=”@drawable/hr”>
</LinearLayout>

<RelativeLayout
android:id=”@+id/user_bg”
android:layout_width
=”fill_parent”
android:layout_height
=”78px”
android:paddingTop
=”8px”
android:paddingLeft
=”15px”
android:background
=”@drawable/u_bg_v”>
<ImageView
android:id=”@+id/user_icon”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_alignParentLeft
=”true”
android:src
=”@drawable/usericon”>
</ImageView>
<TextView
android:id=”@+id/user_name”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_toRightOf
=”@+id/user_icon”
android:layout_marginLeft
=”10px”
android:layout_marginTop
=”18px”
android:textColor
=”#000000″>
</TextView>
<ImageView
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_alignParentRight
=”true”
android:layout_marginRight
=”5px”
android:layout_marginTop
=”10px”
android:src
=”@drawable/sjjt”>
</ImageView>
</RelativeLayout>
<RelativeLayout
android:layout_width=”fill_parent”
android:layout_height
=”fill_parent”>
<ScrollView
android:layout_width=”fill_parent”
android:layout_height
=”fill_parent”
android:paddingLeft
=”17px”
android:paddingRight
=”17px”
android:paddingBottom
=”5px”
android:layout_above
=”@+id/menu_layout”>
<LinearLayout
android:layout_width=”fill_parent”
android:layout_height
=”fill_parent”
android:orientation
=”vertical”>
<TextView
android:id=”@+id/text”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:textColor
=”#000000″
android:textSize
=”15px”>
</TextView>
<ImageView
android:id=”@+id/pic”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”>
</ImageView>
</LinearLayout>
</ScrollView>

<LinearLayout
android:id=”@+id/loadingLayout”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:orientation
=”vertical”
android:visibility
=”gone”
android:layout_centerInParent
=”true”>
<ProgressBar
android:id=”@+id/loading”
android:layout_width
=”31px”
android:layout_height
=”31px”
android:layout_gravity
=”center”
style
=”@style/progressStyle”>
</ProgressBar>
<TextView
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:text
=”正在载入”
android:textSize
=”12px”
android:textColor
=”#9c9c9c”
android:layout_gravity
=”center”
android:layout_below
=”@+id/loading”>
</TextView>
</LinearLayout>

<TableLayout
android:id=”@+id/menu_layout”
android:layout_width
=”fill_parent”
android:layout_height
=”wrap_content”
android:gravity
=”center”
android:layout_alignParentBottom
=”true”
android:layout_marginBottom
=”5px”>
<TableRow
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:gravity
=”center”>
<Button
android:id=”@+id/btn_gz”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:textColor
=”#3882b8″
android:textSize
=”15px”
android:text
=”        关注(1231)”
android:background
=”@drawable/lt_selector”>
</Button>
<Button
android:id=”@+id/btn_pl”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:textColor
=”#3882b8″
android:textSize
=”15px”
android:text
=”        评论(31)”
android:background
=”@drawable/rt_selector”>
</Button>
</TableRow>
<TableRow
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:gravity
=”center”>
<Button
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:textColor
=”#3882b8″
android:textSize
=”15px”
android:layout_gravity
=”left”
android:text
=”刷新”
android:background
=”@drawable/lb_selector”>
</Button>
<Button
android:layout_width=”wrap_content”
android:layout_height
=”wrap_content”
android:textColor
=”#3882b8″
android:textSize
=”15px”
android:text
=”收藏”
android:background
=”@drawable/rb_selector”>
</Button>
</TableRow>

</TableLayout>

</RelativeLayout>
</LinearLayout>

上面这个布局实现起来并不复杂, 主要看看功能按钮区的4个按钮的点击上去的切换背景的效果,以关注按钮为例子看这行设 置,android:background=”@drawable/lt_selector”,在res/drawable-mdpi目录下新建名为 lt_selector.xml用来实现点击上去切换图片的效果,具体代码如下:

代码

<?xml version=”1.0″ encoding=”UTF-8″?>
<selector xmlns:android=”http://schemas.android.com/apk/res/android”>
<item android:state_focused=”false” android:state_selected=”false” android:state_pressed=”false” android:drawable=”@drawable/tbtn_1″ />
<item android:state_pressed=”true” android:drawable=”@drawable/tbtn_h_1″ />
</selector>

本篇虽然看layout文件非常的长,其实仔细看看非常的简单了没有什么难和复杂的了,就是按照前面的经验控制好图片以及控件的显示位置和样式即可,本 篇中用了一个ScrollView控件这个是前面没有用到过的,主要是用来当微博的内容超出显示区域的时候出现滚动条用的这个非常容易使用,所以就简单写 一下到此结束了,请继续关注下一篇阅读微博的功能篇。

[转载]Android开发基础1-概述和SDK安装、文档

mikel阅读(951)

[转载]Android开发基础1-概述和SDK安装、文档 – Thinker – 博客园.

iPhone的软件移植基本结束,可参考http://www.cnblogs.com/2018/category/273921.html,下一步要开始的是Android平台的移植,学习这个的过程中把先把掌握的基础知识整理一下。

综述

www.android.com 开发网址被和谐,SDK官网内容需要翻墙

http://www.android123.com.cn/android_kit.html

Android-sdk_r08-windows.zip

android-ndk-r5-windows.zip

ADT-8.0.0.zip

eclipse-java-europa-winter-win32.zip

由于Android的架构界面部分使用的是JAVA实现的,因此大部分软件都是使用JAVA开发的,此时使用SDK即可;对于已有的C/C++项目的移植问题可以使用NDK(界面由SDK支持)

版本

Android平台

1.5、1.6、2.0、2.1、2.2 2.33.0

Android各版本区别总结

http://blog.csdn.net/lschou520/archive/2010/12/30/6107823.aspx

Android 版本之间的区别[图片]

http://rainhomepage.appspot.com/2010/11/android-version

http://bbs.pcpop.com/100527/6549298.html

IDE安装前置条件(JDK和环境变量)

假设

jdk安装在C:\Program Files (x86)\Java\jdk1.6.0_23

Android SDK解压在D:\mobile\android-sdk-windows

Android NDK解压在D:\mobile\android-ndk-r5

Cygwin安装在C:\cygwin\

JAVA_HOME C:\Program Files (x86)\Java\jdk1.6.0_23
CLASSPATH C:\Program Files (x86)\Java\jdk1.6.0_23\lib;

C:\Program Files (x86)\Java\jdk1.6.0_23\jre\lib

PATH C:\Program Files (x86)\Java\jdk1.6.0_23\bin;找到java的命令行程序

D:\mobile\android-sdk-windows\tools; D:\mobile\android-sdk-windows\platform-tools;

找到adb等工具

C:\cygwin\bin;找到gcc g++ make等C/C++编译工具

D:\mobile\android-ndk-r5找到ndk-buildndk-gdb脚本

SDK

1. 选择安装相应版本的SDK

将sdk包解压到某个目录;在线状态下执行SDK Manager.exe;选择需要的安装包安装,如下图

clip_image002

[文档和例子代码可以在这下载]

2. 建立Virtual devices

根据下载的版本可以建立不同的AVD

clip_image004

3. 运行Eclipse
设置sdk的路径

解压Eclipse; 将Eclipse的anroid开发插件覆盖到eciplse的目录(ADT-8.0.0.zip);执行eclipse.exe

或则使用ADT的在线地址http://dl-ssl.google.com/android/eclipse/联机安装ADT

设置sdk的路径

clip_image006

开始项目

新建:File/New/Android Project可以建立新的项目

clip_image008

这些建立好后可以Run 和Debug程序了

开发文档

SDK Manager.exe选择安装后存放在android-sdk-windows\docs目录下,index.html可查看(最好不用用IE,有的IE版本查看不正常)

clip_image010

对于不太熟悉这个环境的人员,把这个文档过一遍,可以清楚android的一些约定和规范

参考http://www.cnblogs.com/wanlipeng/archive/2010/08/04/1792136.html

[转载]c#扩展方法奇思妙用基础篇六:WhereIf 扩展 - 鹤冲天 - 博客园

mikel阅读(1304)

[转载]c#扩展方法奇思妙用基础篇六:WhereIf 扩展 – 鹤冲天 – 博客园.

一、Where 扩展的不足

如下界面,可通过姓名、编号和地址对人员进行模糊查询:

PersonQuery

我们通常会写出如下代码:

public IQueryable<Person> Query(IQueryable<Person> source, string name, string code, string address)
{
    var result = source;
    if(string.IsNullOrEmpty(name) == false)
        result = source.Where(p => p.Name.Contains(name));
    if (string.IsNullOrEmpty(code) == false)
        result = source.Where(p => p.Code.Contains(code));
    if (string.IsNullOrEmpty(address) == false)
        result = source.Where(p => p.Code.Contains(address));
    return result;
}

以上代码有大量的 if 显得很繁琐,代码可读性不好。

二、创建并使用 WhereIf 扩展

WhereIf 扩展比较简单,代码如下:

public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate, bool condition)
{
    return condition ? source.Where(predicate) : source;
}

上面的代码可简化成:

public IQueryable<Person> Query(IQueryable<Person> source, string name, string code, string address)
{
    return source
        .WhereIf(p => p.Name.Contains(name), string.IsNullOrEmpty(name) == false)
        .WhereIf(p => p.Code.Contains(code), string.IsNullOrEmpty(code) == false)
        .WhereIf(p => p.Code.Contains(address), string.IsNullOrEmpty(address) == false);
}

是不是更易读一些!

当然,我们还需要一个 IEnumerable<T> 版本的 WhereIf 扩展,方便对集合进行查询:

public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool condition)
{
    return condition ? source.Where(predicate) : source;
}

三、WhereIf 完整代码

namespace System.Linq
{
    public static class WhereIfExtension
    {
        public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, int, bool>> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, int, bool> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
    }
}

将类放入 System.Linq 命名空间中,随时使用,更方便。

[转载]SQLite做为本地缓存的应用需要注意的地方

mikel阅读(991)

[转载]SQLite做为本地缓存的应用需要注意的地方 – Tecky‘s Blog – 博客园.

今天看到了园友陆敏计的一篇文章<<C#数据本地存储方案之SQLite>>, 写到了SQLite的诸多优点,尤其适应于本地数据缓存和应用程序。

转自陆兄的内容,来夸夸SQLite:

SQLite官方网站: http://www.sqlite. org/ 时第一眼看到关于SQLite的特性。

1. ACID事务

2. 零配置 – 无需安装和管理配置

3. 储存在单一磁盘文件中的一个完整的数据库

4. 数据库文件可以在不同字节顺序的机器间自由的共享

5. 支持数据库大小至2TB

6. 足够小, 大致3万行C代码, 250K

7. 比一些流行的数据库在大部分普通数据库操作要快

8. 简单, 轻松的API

9. 包含TCL绑定, 同时通过Wrapper支持其他语言的绑定

10. 良好注释的源代码, 并且有着90%以上的测试覆盖率

11. 独立: 没有额外依赖

12. Source完全的Open, 你可以用于任何用途, 包括出售它

13. 支持多种开发语言,C, PHP, Perl, Java, ASP .NET,Python

正好前一段时间我做了这方面的应用,我就结合陆兄的这篇文章,谈谈我在Sqlite本地缓存业务数据时的经验,给大家借鉴一下。我开发时比较仓促,很多地方请大家多提意见。

解决的问题

首先介绍我用Sqlite解决的实际问题是什么?

问题1:某个功能的数据需要连接一个远程数据库查询速度很慢,查一次数据不容易,希望能够重复利用之前查过的数据集。

问 题2:非常大的数据量比如几千万甚至几亿条数据,一次性读取到DataTable中,会内存溢出的,所以在第一次分析时就是通过Reader的方式,分析 完一条后并不在内存中保存,但是紧接着用户的第二次分析、第三次分析还是要用到的第一次分析的数据,如果我们重新查询一次远程服务器,效率可想而知啊。

结合上面的2个问题,为了解决效率问题和数据重复利用度,减少数据库服务器的压力,我才用Sqlite缓存数据(当然这不是唯一也不是最好的解决方案) 。

优化SQLiteHelper

陆兄的SQLiteHelper类我增加了几个有用的方法:

第一个方法是GetSchema,得到某个表的表结构。

        /// <summary>   
        /// 查询数据库中的所有数据类型信息   
        /// </summary>   
        /// <returns></returns>   
        public DataTable GetSchema()
        {
            using (SQLiteConnection connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                DataTable data = connection.GetSchema("TABLES");
                connection.Close();
                //foreach (DataColumn column in data.Columns)   
                //{   
                //    Console.WriteLine(column.ColumnName);   
                //}   
                return data;
            }
        }

第二个方法是IsTableExist,判断SQLite数据库重某个表是否存在 。

        /// <summary>   
        /// 判断SQLite数据库表是否存在  
        /// </summary>   
        /// <param name="dbPath">要创建的SQLite数据库文件路径</param>   
        public bool IsTableExist(string tableName)
        {
            using (SQLiteConnection connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                using (SQLiteCommand command = new SQLiteCommand(connection))
                {

                    command.CommandText = "SELECT COUNT(*) FROM sqlite_master where type='table' and name='" + tableName + "'";
                    int iaaa = Convert.ToInt32(command.ExecuteScalar());
                    if (Convert.ToInt32(command.ExecuteScalar()) == 0)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
            }
        }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas,”Courier New”,courier,monospace; background-color: rgb(255, 255, 255); }.csharpcode pre { margin: 0em; }.csharpcode .rem { color: rgb(0, 128, 0); }.csharpcode .kwrd { color: rgb(0, 0, 255); }.csharpcode .str { color: rgb(0, 96, 128); }.csharpcode .op { color: rgb(0, 0, 192); }.csharpcode .preproc { color: rgb(204, 102, 51); }.csharpcode .asp { background-color: rgb(255, 255, 0); }.csharpcode .html { color: rgb(128, 0, 0); }.csharpcode .attr { color: rgb(255, 0, 0); }.csharpcode .alt { background-color: rgb(244, 244, 244); width: 100%; margin: 0em; }.csharpcode .lnum { color: rgb(96, 96, 96); }

第三个方法是Query,执行查询语句,返回DataSet

        /// <summary>
        /// 执行查询语句,返回DataSet
        /// </summary>
        /// <param name="SQLString">查询语句</param>
        /// <returns>DataSet</returns>
        public DataSet Query(string SQLString)
        {
            using (SQLiteConnection connection = new SQLiteConnection(connectionString))
            {
                DataSet ds = new DataSet();
                try
                {
                    connection.Open();
                    SQLiteDataAdapter command = new SQLiteDataAdapter(SQLString, connection);
                    command.Fill(ds, "ds");
                }
                catch (System.Data.SQLite.SQLiteException ex)
                {
                    throw new Exception(ex.Message);
                }
                return ds;
            }
        }

构建缓存对象模型和缓存控制器

每一块缓存对象,在数据库中会产生一个表,而表名称是有缓存控制器自动生成的,访问缓存的工作全部交由缓存控制器完成,通过缓存项的ID和ModuleKey来访问。

在Sqlite中还需要一个系统表来维护每个缓存项和实际缓存存储表之间的对应关系,我们称之为配置表,它将在缓存控制器创建Sqlite缓存数据库文件时创建。

配置表共有以下几个字段,分别和缓存对象模型CdlCacheItem类映射:

列名称 说明
Id 缓存的唯一数字编号
ModuleKey 缓存模块名称,一个模块可以有多个缓存数据,ID可以区分。实际应用时,某个功能时会经常缓存数据的,所以通过ModuleKey就可以得到这个功能所有的缓存列表,然后选定其中的部分缓存来进行使用。
Comments 缓存说明
TableName 缓存数据存储的数据表名称
AddDate 缓存时间戳

创建数据库的方法如下:

        static void CreateDB()
        {
            //总共有ID、ModuleKey、Comments、AddDate这几列
            string sql = "CREATE TABLE SYSCDLTABLES(ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,MODULEKEY VARCHAR(200),COMMENTS VARCHAR(500),TABLENAME VARCHAR(100),ADDDATE DATETIME)";
            SQLiteDBHelper.CreateDB(CACHEFILEPATH, sql);
        }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas,”Courier New”,courier,monospace; background-color: rgb(255, 255, 255); }.csharpcode pre { margin: 0em; }.csharpcode .rem { color: rgb(0, 128, 0); }.csharpcode .kwrd { color: rgb(0, 0, 255); }.csharpcode .str { color: rgb(0, 96, 128); }.csharpcode .op { color: rgb(0, 0, 192); }.csharpcode .preproc { color: rgb(204, 102, 51); }.csharpcode .asp { background-color: rgb(255, 255, 0); }.csharpcode .html { color: rgb(128, 0, 0); }.csharpcode .attr { color: rgb(255, 0, 0); }.csharpcode .alt { background-color: rgb(244, 244, 244); width: 100%; margin: 0em; }.csharpcode .lnum { color: rgb(96, 96, 96); }每个缓存项(缓存对象模型)定义如下,和配置表对应:

    /// <summary>
    /// 缓存项对象
    /// </summary>
    /// <Author>Tecky Lee</Author>
    /// <Date>2011-1-11 15:11</Date>
    public class CdlCacheItem
    {
        int m_id;

        public int Id
        {
            get { return m_id; }
            set { m_id = value; }
        }
        string m_moduleKey;

        public string ModuleKey
        {
            get { return m_moduleKey; }
            set { m_moduleKey = value; }
        }
        string m_comments;

        public string Comments
        {
            get { return m_comments; }
            set { m_comments = value; }
        }
        string m_tableName;

        public string TableName
        {
            get { return m_tableName; }
            set { m_tableName = value; }
        }
        DateTime m_timestamp;

        public DateTime Timestamp
        {
            get { return m_timestamp; }
            set { m_timestamp = value; }
        }
    }

下面是控制器的接口定义:

public interface ICdlCacheController
    {
        void BeginLoadRow();
        void EndLoadRow();
        System.Collections.Generic.IList<CdlCacheItem> GetCdlCacheItems(string moduleKey);
        CdlCacheItem GetCdlCacheItems(int id);
        void LoadRow(System.Data.DataRow row, string tableName);
        void LoadRow(IEnumerable<object> row, string tableName);
        string LoadTable(System.Data.DataTable dt, string moduleKey, string comments);
        System.Data.Common.DbDataReader QueryCdlTableReader(CdlCacheItem item);
        System.Data.DataTable QueryCdlTables(CdlCacheItem item);
        System.Data.DataTable QueryCdlTables(string sql);
        void RemoveAllTables();
        void RemoveCdlTables(string moduleKey);
        void RemoveCdlTables(System.Collections.Generic.IList<CdlCacheItem> items);
        void RemoveCdlTables(CdlCacheItem item);
        void RemoveCdlTables(int id);
    }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas,”Courier New”,courier,monospace; background-color: rgb(255, 255, 255); }.csharpcode pre { margin: 0em; }.csharpcode .rem { color: rgb(0, 128, 0); }.csharpcode .kwrd { color: rgb(0, 0, 255); }.csharpcode .str { color: rgb(0, 96, 128); }.csharpcode .op { color: rgb(0, 0, 192); }.csharpcode .preproc { color: rgb(204, 102, 51); }.csharpcode .asp { background-color: rgb(255, 255, 0); }.csharpcode .html { color: rgb(128, 0, 0); }.csharpcode .attr { color: rgb(255, 0, 0); }.csharpcode .alt { background-color: rgb(244, 244, 244); width: 100%; margin: 0em; }.csharpcode .lnum { color: rgb(96, 96, 96); }

上面的函数下面来做个说明:

1、BeginLoadRow、LoadRow和EndLoadRow,三个函数组为了在我们查询主数据库时使用Reader方式读取数据时,可以一条条将数据同时存放在缓存中。

2、RemoveAllTables和RemoveCdlTables是用来删除缓存项的。

3、GetCdlCacheItems,通过moduleKey得到多个缓存项。比如用户想基于这几天内保存的某个功能的数据做一次快速分析,那么我们就可以通过这个函数得到缓存列表,由用户选择列表中的一个来继续。

4、QueryCdlTableReader,得到某个缓存数据的Reader对象,这样可以一行行的分析,一次读出大数据量的数据到DataTable中,内存可能会溢出的。

5、QueryCdlTables,将某个缓存项查询并装载到DataTable中。

提高缓存数据写入效率

Sqlite在保存数据的时候,比如一次保存一个亿条的数据,一条条插入效率非常低下,网上也有人对其进行讨论。

效率低下的主要原因在于IO操作次数过于频繁,所以在LoadTable或者是使用BeginLoadRow·EndLoadRow的时候,使用了 事务来减少数据提交的次数,结果保存的效率非常的高,我测试的结果是400万条数据查询,只需要几十秒钟,这点时间相对于重新查一次远程服务器那是可以忽 略了。

下面给出BeginLoadRow和EndLoadRow的具体代码(只有在EndRow的时候才会提交一次数据):

        SQLiteConnection m_connection;
        SQLiteCommand m_command;
        DbTransaction m_transaction;
        public void BeginLoadRow()
        {
            m_connection = new SQLiteConnection("Data Source=" + CACHEFILEPATH);

            m_connection.Open();
            m_transaction = m_connection.BeginTransaction();
            m_command = new SQLiteCommand(m_connection);
        }
        public void EndLoadRow()
        {
            try
            {
                if (m_command != null)
                    m_command.Dispose();

                if (m_transaction != null)
                {
                    m_transaction.Commit();
                }

                if (m_connection != null)
                {
                    m_connection.Close();
                    m_connection.Dispose();
                }
            }
            catch (System.Exception ex)
            {
                LogHandle.Error(ex);
            }
        }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas,”Courier New”,courier,monospace; background-color: rgb(255, 255, 255); }.csharpcode pre { margin: 0em; }.csharpcode .rem { color: rgb(0, 128, 0); }.csharpcode .kwrd { color: rgb(0, 0, 255); }.csharpcode .str { color: rgb(0, 96, 128); }.csharpcode .op { color: rgb(0, 0, 192); }.csharpcode .preproc { color: rgb(204, 102, 51); }.csharpcode .asp { background-color: rgb(255, 255, 0); }.csharpcode .html { color: rgb(128, 0, 0); }.csharpcode .attr { color: rgb(255, 0, 0); }.csharpcode .alt { background-color: rgb(244, 244, 244); width: 100%; margin: 0em; }.csharpcode .lnum { color: rgb(96, 96, 96); }

LoadTable函数内部也是调用BeginLoadRow·EndLoadRow模式来完成的。

数据库文件如何创建:

Sqlite数据库文件如果不存在,在执行sql语句的时候,会自动根据ConnetionString中指定的位置创建数据库文件,默认创建的空数据库只有4K。

其他有待讨论的问题:

1、我是将所有的缓存做到一个数据库文件中了,实际应用根据业务的不同,可以一份缓存数据一个文件也是很好管理的,维护也方便,资源管理器中就可以拷贝删除等。

2、当我们存储一亿条数据到Sqlite的时候,因为Sqlite没有压缩数据,结果数据库文件就可以会有好几个G(这也不一定,适合数据库字段的多少,字段类型有关的)。

文件太大就消耗了磁盘空间,而且用户或者程序如果不及时清理的,可能会耗尽磁盘空间。

这里就必须建立一个机制,检查sqlite的缓存并及时清理,或者设置缓存应用的上限,当达到上限后自动根据时间戳清理历史缓存。

[转载]Android 中文 API (101) —— AsyncTask

mikel阅读(987)

[转载]Android 中文 API (101) —— AsyncTask – 农民伯伯 – 博客园.

前言

本章内容是Android.os.AsyncTask,版本为Android 2.3 r1,翻译来自”0_1″,欢迎访问它的博客:”http://dev.10086.cn/blog/?32546“,再次感谢”0_1” !期待你一起参与Android API的翻译,联系我over140@gmail.com。

声明

欢迎转载,但请保留文章原始出处:)

博客园:http://www.cnblogs.com/

Android中文翻译组:http://goo.gl/6vJQl

正文

一、结构

public abstract class AsyncTask extends Object

java.lang.Object

android.os.AsyncTask<Params, Progress, Result>

二、类概述

AsyncTask能够适当地、简单地用于 UI线程。 这个类不需要操作线程(Thread)就可以完成后台操作将结果返回UI

异步任务的定义是一个在后台线程上运行,其结果是在 UI线程上发布的计算。 异步任务被定义成三种泛型类型: ParamsProgressResult;和四个步骤: begin , doInBackgroundprocessProgressend

三、用法

AysncTask必须被继承使用。子类至少覆盖一个方法 (doInBackground(Params...)),最经常覆盖另一个(onPostExecute(Result).)下面是一个子类的例子:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL… urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize
+= Downloader.downloadFile(urls[i]);
publishProgress((
int) ((i / (float) count) * 100));
}
return totalSize;
}

protected void onProgressUpdate(Integer… progress) {
setProgressPercent(progress[
0]);
}

protected void onPostExecute(Long result) {
showDialog(
Downloaded + result + bytes);
}
}

一旦创建,一个任务执行起来就非常简单:

new DownloadFilesTask().execute(url1, url2, url3);

四、AsyncTask的泛型类型

这三个类型被用于一个异步任务,如下:

1. Params启动任务执行的输入参数

2. Progress后台任务执行的百分比

3. Result,后台计算的结果类型

在一个异步任务里,不是所有的类型总被用。假如一个类型不被使用,可以简单地使用 Void类型:

private class MyTask extends AsyncTask<Void, Void, Void> { … }

五、4个步骤

当一个异步任务被执行,任务经过四各步骤:

1onPreExecute(),在UI线程上调用任务后立即执行。这步通常被用于设置任务,例如在用户界面显示一个进度条。

2doInBackground(Params...),后台线程执行onPreExecute()完后立即调用,这步被用于执行较长时间的后台计算。异步任务的参数也被传到这步。计算的结果必须在这步返回,将传回到上一步。在执行过程中可以调用publishProgress(Progress...)来更新任务的进度。

3onProgressUpdate(Progress...),一次呼叫 publishProgress(Progress...)后调用 UI线程。执行时间是不确定的。这个方法用于当后台计算还在进行时在用户界面显示进度。例如:这个方法可以被用于一个进度条动画或在文本域显示记录。

4onPostExecute(Result), 当后台计算结束时,调用 UI线程。后台计算结果作为一个参数传递到这步。

六、线程规则

有一些线程规则必须去遵守,这个类才会正确的工作:

任务实例必须创建在 UI线程

execute(Params...)必须在UI线程上调用

不要手动调用onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...)

这个任务只执行一次(如果执行第二次将会抛出异常)

七、内部类

enum       AsyncTask.Status

表示任务的当前状态

八、构造函数

public AsyncTask ()

创建一个新的异步任务。这个构造函数必须在UI线程上调用。

九、公共方法

public final boolean cancel (boolean mayInterruptIfRunning)

尝试取消这个任务的执行,如果这个任务已经结束或者已经取消或者不能被取消或者某些其他原因,那么将导致这个操作失败,当调用此方法时,此方法执行成功并且这个任务还没有执行,那么此任务将不再执行。如果任务已经开始,这时执行此操作传入的参数mayInterruptIfRunningtrue,执行此任务的线程将尝试中断该任务。

参数

mayInterruptIfRunning 如果为true则正在执行的线程将会中断,如果false,则会允许正在执行的任务线程执行完毕。

返回值

如果此任务不能取消返回false,如果已经正常的执行完毕,返回true

参见

isCancelled()

onCancelled()

public final AsyncTask<Params, Progress, Result> execute (Params… params)

用指定的参数来执行此任务,这个方法将会返回此任务本身,所以调用者可以拥有此任务的引用。此方法必须在UI线程中调用

参数

params  任务参数

返回值

AsyncTask的实例

异常

IllegalStateException 如果getStatus()返回的是RUNNING或者FINISHED

public final Result get ()

等待计算结束并返回结果

返回值

计算结果

异常

CancellationException 如果计算取消

ExecutionException 如果计算抛出异常

InterruptedException 当等待时当前线程抛出异常

public final Result get (long timeout, TimeUnit unit)

等待计算结束并返回结果,最长等待时间为:timeOut(超时时间).

参数

timeout 计算等待超时时间

unit 超时的时间单位

返回值

计算结果

异常

CancellationException 如果计算取消

ExecutionException 如果计算抛出异常

InterruptedException 当等待时当前线程抛出异常

TimeoutException 等待时间超时

public final AsyncTask.Status getStatus ()

获得任务的当前状态

返回值

当前状态

public final boolean isCancelled ()

如果在任务正常结束之前取消任务成功则返回true,否则返回false

返回值

如果任务正常结束之前取消任务成功返回true

参见

cancel(boolean)

十、受保护方法

protected abstract Result doInBackground (Params… params)

覆盖此方法在后台线程执行计算,此方法中的参数是此任务的execute(Params...)方法的调用这传递的参数,此方法可以调用publishProgress(Progress...)UI线程中来更新数据

参数

params  此任务的参数

返回值

返回一个由此任务子类定义的结果 Result

参见

onPreExecute()

onPostExecute(Result)

publishProgress(Progress...)

protected void onCancelled ()

此方法在UI线程中当cancel(boolean) 被调用后调用

参见

cancel(boolean)

isCancelled()

protected void onPostExecute (Result result)

此方法在UI线程中doInBackground(Params...)。方法调用之后调用,此方法中的参数的值是doInBackground(Params...)的返回值或者当此任务已经被取消或有异常发生时此参数值为空null

参数

result doInBackground(Params...)计算出的操作的结果。

参见

onPreExecute()

doInBackground(Params...)

protected void onPreExecute ()

在方法doInBackground(Params...)调用之前调用

参见

onPostExecute(Result)

doInBackground(Params...)

protected void onProgressUpdate (Progress… values)

该方法在UI线程中publishProgress(Progress...)被调用之后调用,该方法中的参数values是已经被传递到publishProgress(Progress...)中的参数

参数

values 进度表示值

参见

publishProgress(Progress...)

doInBackground(Params...)

protected final void publishProgress (Progress… values)

当调用doInBackground(Params...)在后台执行计算时会调用该方法,每当在UI线程中调用此方法时将触发onProgressUpdate(Progress...)方法的执行

参数

values 将进度值更新到UI

参见

onProgressUpdate(Progress...)

doInBackground(Params...)

十一、补充

文章精选

Android AsyncTask理解

TabActivity下在AsyncTask中使用ProgressDialog存在问题的解决方法

小心,AsyncTask 不是萬能的[blogspot]

十二、公告

内部类、内部接口由于内容较少均不再单独发布。

结束

随着春节的结束,翻译组工作重新回到正轨,感谢大家的关注与支持!

——————————————————————————————————————————

AsyncTask.Status

一、结构

public static final enum AsyncTask.Status extends Enum<E extends Enum<E>>

java.lang.Object

java.lang.Enum<E extends java.lang.Enum<E>>

android.os.AsyncTask.Status

二、类概述

标志任务的当前状态,每个状态在任务的生命周期中只会出现一次。

三、枚举值

public static final AsyncTask.Status FINISHED

标志onPostExecute(Result)方法已经结束

public static final AsyncTask.Status PENDING

标志任务还没有执行

public static final AsyncTask.Status RUNNING

标志任务正在执行

[转载]构建高性能ASP.NET站点 第七章 如何解决内存的问题(前篇)—托管资源优化—垃圾回收机制深度剖析

mikel阅读(1057)

[转载]【原创】构建高性能ASP.NET站点 第七章 如何解决内存的问题(前篇)—托管资源优化—垃圾回收机制深度剖析 – ASP.NET 架构 – 博客园.

构建高性能ASP.NET站点 第七章 如何解决内存的问题(前篇)—托管资源优化垃圾回收机制剖析

前言:本章主要详细的讲述如何因内存问题而导致的性能问题,很多的时候都是深入.NET内核进行分析,然后给出解决方案,同时,本系列的其他文章,也争取做到:深入浅出。

本篇是为后面的做个铺垫,而且比较的精彩。只有真正的理解了本篇,后面才可以顺利的走下去。

本篇的议题如下:

内存问题概述(前篇)

托管资源优化(前篇)

对象的生命周期(前篇)

对象的代“(前篇)

大对象堆(LOH) (前篇)

CLR计数器的使用 (前篇)

CLR Profiler的使用(中篇)

垃圾回收器的不同版本(中篇)

对象使用注意事项(中篇)

常用优化措施(后篇)

非托管资源优化

Session会话的优化

内存问题概述

CPU一样,内存也是一个直接影响服务端性能的重要的硬件资源。

一般来说,如果服务端内存不足,从导致以下两个问题产生:

1. 导致服务端把一些原本要写到内存中的数据,写到硬盘上面。这样不仅仅加大了CPU和磁盘的I/O操作,同时也延长了读取这些数据的时间。

2. 阻止了一些缓存策略的使用。

对于内存不足,一直最快最直接的方式就是去买内存条加在服务器上面。但是这样存在一个隐患的问题就是:如果加了新的内存之后,服务端又面临内存不足的问 题,我们不可能无止境的加内存条,那么我们就必须从站点本身来解决这个问题,例如从服务端的配置,对站点的代码进行分析,优化。

托管资源优化

对于托管资源,相信大家并不陌生了,简单的说就是:在C#的托管堆上面创建的资源,或者说通过new产生的对象。

在深入讲解之前,我们首先来看看对象的生命周期

对象的生命周期

当我们用new关键字创建了一个对象的时候,这个对象就被分配到CRL托管堆上面。这个托管堆是在内存中的。而且这个分配对象空间的速度是非常的快的,因为每次都是在托管堆的最后面划出一定的空间来给这个对象,不用去堆上面需找合适大小的空间。

如果当托管堆准备为一个对象分配空间的时候,发现托管堆上面的空间太小了,不足以分配给这个新的对象,那么CLR就开始运行垃圾回收机制了。我们知道:垃圾回收机制会把那些在托管堆上面没有了引用指向的那些对象都清理掉,同时也会把托管堆上面现存的对象进行压缩。

但是有一点需要清楚:如果此时进行了垃圾回收的时候,清除了一些没有用的对象,但是只有在下一次来回收进行的时候,上次垃圾回收清除的对象才真正的从内存中消除(此时,还有一些“对象复苏“等话题就不在赘述)

下面就来讲述一些垃圾回收的话题。

对象的代“

CLR进行垃圾回收的时候,垃圾回收器回去托管堆上面去检查对象是否可以被回收,这个检查过程是非常消耗资源的。为了避免每次垃圾回收都要便利托管堆上面的所有对象,CLR给把托管堆上面的对象用来划分,例如,第一代,第二代。然后每次便利扫描托管堆的时候,就去扫描某一个中的对象,这样性能就好点。

在托管堆上面,可以把对象分为三个”:0代,1代,2代,仅此这三个代。每个对象都是从0代开始的。一个对象每经历一次垃圾回收,并且这个对象还在使用中,那么这个对象的“代“就会增加1代。例如,如果在0代的对象,经历了一次垃圾回收之后,他的代就是1代,如果是1代的对象,最后就会变为2代。如果对象本身已经是2代了,不管经历多少次垃圾回收(如果对象一直在使用),那么这个对象还是2代。

CLR垃圾回收中有句话要记得:”数越大,被回收的可能性就越小。而且一些性能优化就是根据这个进行的。

每次CLR在进行垃圾回收的时候,都会优先的去扫描第0代的对象,所以,一些新的,临时使用的对象可以被立刻的清除。相比而言,垃圾回收器扫描第1代对象的频率就没有第0代强,扫描第2代对象的频率就更低了。所以说:对象存活的时间越长,就越难被回收,而且一直占据CLR的内存资源。

还有有点需要注意的就是:如果CLR决定要扫描了第1代了,同时也用扫描第0代的对象,同时如果,CLR扫描第2代对象,那么第0代,第1代对象都会被扫描。

所以,从这里可以得出:我们尽量避免把原本需要立刻回收的的对象变为长期存活的对象。通俗点说就是:如果一个对象本来已经存活在0代的,然后用完就回收的,我们不要让这个对象一直存活到第1代,甚至第2代。在编程上面基本就是这样的实现思路:尽可能晚的实例化对象,尽可能早的释放对象。

大对象堆(Large Objecet Heap)

我们之前讲述了的一些话题,CLR除了上面的一般的堆(一般的new对象分配空间的那个堆)CLR中还存在另外的一个堆:专门用来放置那些大于了85k的对象的堆,大对象堆

如果new一个对象的时候,这个对象的大小超过了85k,那么CLR就会把这个对象放在LOH上面。如果此时LOH的空间不足了,那么CLR就会启动垃圾回收器去扫描LOH堆和那个一般堆上面的第2代对象,我们之前说过,如果扫描第2代对象,就同时扫描第1代,第0代,那么实际相当于扫描了整个托管堆,性能影响可想而知。

而且不想之前那个一般堆,在LOH上面的对象被垃圾回收器回收之后,上面的大对象是不会被压缩的,那么LOH这个堆上面就可能存在一些空间碎片,然后分配新的大对象的时候,就要找空间,甚至进行碎片的整理,大家可以联想一下我们电脑的磁盘碎片整理。

OK,今天就讲到这里,理论有点多,但是都是基本要清楚和掌握的,希望多多理解。

[转载]ASP.NET MVC开发人员必备的五大工具

mikel阅读(920)

[转载]ASP.NET MVC开发人员必备的五大工具_IT新闻_博客园.

1. Chirpy Zippy

下载地址:http://chirpy.codeplex.com/

过去,在将JavaScript脚本和CSS文件部署到Web服务器之 前,我习惯使用压缩工具进行压缩再部署,安装Chirpy后,你的脚本和CSS文件将会基于其名字自动压缩,例如,假设你有一个名叫 myscript.js的脚步文件想要压缩,只要你将其重命名为myscript.yui.js,它就会调用YUI压缩程序自动压缩,压缩后的文件在解决 方案资源管理器中显示为一个子项目,你可以继续查看和调试未经压缩的脚本。

使用方法请参考这里

2. T4MVC

下载地址:http://mvccontrib.codeplex.com/

我曾经写过许多关于T4MVC的博文,但这里仍然值得一提,它是ASP.NET MVC应用程序的一个T4模板,简化了创建控制器、行为和视图的操作,使MVC代码的可维护性更好。

3. MVC Contrib

下载地址:http://mvccontrib.codeplex.com/

T4MVC是MVC Contrib库的一小部分,MVC Contrib库包含了ASP.NET MVC开发领域的各种工具,我在最近的一个私人项目中就使用了Grid HTML Helper,但MVC Contrib包含的功能和库很多,需要你在日常开发中逐一去发现。

4. ASP.NET精灵和图像优化框架

下载地址:http://aspnet.codeplex.com/releases/view/50869

提高网站性能最好的办法就是减少渲染一个页面需要的HTTP请求数量,减少请求数的一个方法是使用CSS精灵或内嵌图像。例如,假设你的网站有 一个工具条,包含12个32×32像素的图标,加载页面时至少会产生12个HTTP请求,即每个小图标都会产生一个HTTP请求,CSS精灵将所有图标编 结在一起,然后使用CSS定义每个图像的边界,这样可以将请求数减少到1个。

遗憾的是,创建精灵的过程非常耗时和繁琐,基本上需要合并所有图像,然后在样式表中声明每个图像的X和Y坐标,如果合并图像和生成CSS的过程能够自动化就好了,有需求就有对应的产品,ASP.NET精灵和图像优化框架于是就应运而生了。

5. ELMAH

下载地址:http://code.google.com/p/elmah/

ELMAH是一款优秀的MVC应用程序日志记录工具,如果你还没有用过它,强烈建议你试一试,虽然需要一翻设置,但其功能的确很强大,这里列一个快速清单以供参考:

  • 记录几乎所有未处理的异常;
  • 通过网页远程查看全部日志;
  • 通过网页远程查看任何单条日志的详细信息;
  • 即使customErrors模式关闭,大多数时候,你可以查看ASP.NET因异常产生的原始黄色死机屏幕;
  • 发生错误时会自动发送一封电子邮件通知;
  • RSS种子提供最后15个错误日志的信息。

[转载]Web开发者必备的20款超赞jQuery插件

mikel阅读(1057)

[转载]Web开发者必备的20款超赞jQuery插件 – 梦想天空 – 博客园.

JQuery的易扩展性吸引了来自全球的开发者来共同编写JQuery插件。JQuery插件不仅能够增强网站的可用性,有效地改善用户体验,还可以大大减少开发时间。现在的jQuery插件很多,可以根据您的项目需要来选择。这里为您介绍20款非常不错的插件。



Creative Radical Web Typography

Lettering.js是一个轻量经的、易于使用的jQuery插件,可创造出极具个性的网页排版,是2010年最佳jQuery插件之一。

New FancyMoves Jquery Product Slider

Jquery Product Slider是一款效果很不错的产品幻灯片插件。

Jquery Space Gallery

Jquery Space Gallery是一款很有空间感的图片库插件。

Fancy Thumbnail Hover Effect

这是一款非常不错的Hover效果插件。

Jquery Inline Form Validation

这是一款表单验证插件。

Site Switcher

这是一款站点切换插件。

AnythingSlider

这是一款效果很棒的幻灯片插件。

Jquery Tooltip Coda Bubble

这是一款简洁的jQuery信息提示插件。

Jquery Upload and Crop Image

这是一款图片上传和裁剪插件。

jQuery Carts

这是一款jQuery图表插件。

Twitter-like login box

这是一款类似Twitter登陆框效果的插件。

File Download

这是一款文件下载插件。

Polaroid Photo Viewer

这是一款宝丽莱效果图片浏览插件。

jquery Hover Sub Tag Cloud

这是一款子标签云显示插件。

Graph Visualization

这是一款图标可视化插件。

Show/Hide Jquery Panel

这是一款控制面板显示和隐藏的插件。

Drop Down with CSS and jQuery

这是一款下拉菜单插件。

Quick & Easy Zooming With jQuery – Zoomy

这是一款非常好用的缩放插件。

Horizontal Accordions

这是一款横向手风琴效果插件。

Flexible Rating

这是一款非常灵活的评分插件。

(编译来源:梦想天空 原文来自:20 Useful jQuery Plugins Every Developer Should Know About

[转载]android开发我的新浪微博客户端-用户首页面功能篇(5.2)

mikel阅读(737)

[转载]android开发我的新浪微博客户端-用户首页面功能篇(5.2) – 遇见未知的自己 – 博客园.

上一篇完成用户首页的UI实现,本篇接下来讲功能部分的实现,本页面主要的功能就用户关注的最新微博列表,从上一篇中知道本列表是用ID为Msglist的ListView控件来实现,本篇的主要就讲解如果获取微博列表数据给这个ListView提供显示数据。ListView每一条子数据分别由用户头像、用户昵称、发布时间、是否包含照片、微博内容这五部分组成,根据这五部分定义一个名为WeiBoInfo.java实体类,代码如下:

代码

public class WeiBoInfo {
//文章id
private String id;
public String getId(){
return id;
}
public void setId(String id){
this.id=id;
}
//发布人id
private String userId;
public String getUserId(){
return userId;
}
public void setUserId(String userId){
this.userId=userId;
}

//发布人名字
private String userName;
public String getUserName(){
return userName;
}
public void setUserName(String userName){
this.userName=userName;
}

//发布人头像
private String userIcon;
public String getUserIcon(){
return userIcon;
}
public void setUserIcon(String userIcon){
this.userIcon=userIcon;
}

//发布时间
private String time;
public String getTime(){
return time;
}
public void setTime(String time)
{
this.time=time;
}

//是否有图片
private Boolean haveImage=false;
public Boolean getHaveImage(){
return haveImage;
}
public void setHaveImage(Boolean haveImage){
this.haveImage=haveImage;
}

//文章内容
private String text;
public String getText(){
return text;
}
public void setText(String text){
this.text=text;
}

}

然后在res/layout目录下新建名为weibo.xml的Layout用来控制ListView子项的显示部件,代码很简单不多解释了,直接看下面代码:

代码

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout
xmlns:Android=”http://schemas.Android.com/apk/res/android”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:orientation
=”horizontal”>
<ImageView
android:id=”@+id/wbicon”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:src
=”@drawable/usericon”
android:layout_margin
=”8px”>
</ImageView>
<LinearLayout
android:layout_width=”fill_parent”
android:layout_height
=”wrap_content”
android:orientation
=”vertical”
android:paddingLeft
=”0px”
android:paddingRight
=”5px”
android:layout_marginTop
=”5px”
android:layout_marginBottom
=”5px”>
<RelativeLayout
android:layout_width=”fill_parent”
android:layout_height
=”wrap_content”>
<TextView
android:id=”@+id/wbuser”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:textSize
=”15px”
android:textColor
=”#424952″
android:layout_alignParentLeft
=”true”>
</TextView>
<ImageView
android:id=”@+id/wbimage”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_marginTop
=”3px”
android:layout_marginRight
=”5px”
android:layout_toLeftOf
=”@+id/wbtime”>
</ImageView>
<TextView
android:id=”@+id/wbtime”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:layout_alignParentRight
=”true”
android:textColor
=”#f7a200″
android:textSize
=”12px”>
</TextView>
</RelativeLayout>
<TextView
android:id=”@+id/wbtext”
android:layout_width
=”wrap_content”
android:layout_height
=”wrap_content”
android:textColor
=”#424952″
android:textSize
=”13px”
android:layout_marginTop
=”4px”>
</TextView>
</LinearLayout>
</LinearLayout>

接下来为列表控件定义一个数据Adapter,代码如下:

代码

private List<WeiBoInfo> wbList;

//微博列表Adapater
public class WeiBoAdapater extends BaseAdapter{

private AsyncImageLoader asyncImageLoader;

@Override
public int getCount() {
return wbList.size();
}

@Override
public Object getItem(int position) {
return wbList.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
asyncImageLoader
= new AsyncImageLoader();
convertView
= LayoutInflater.from(getApplicationContext()).inflate(R.layout.weibo, null);
WeiBoHolder wh
= new WeiBoHolder();
wh.wbicon
= (ImageView) convertView.findViewById(R.id.wbicon);
wh.wbtext
= (TextView) convertView.findViewById(R.id.wbtext);
wh.wbtime
= (TextView) convertView.findViewById(R.id.wbtime);
wh.wbuser
= (TextView) convertView.findViewById(R.id.wbuser);
wh.wbimage
=(ImageView) convertView.findViewById(R.id.wbimage);
WeiBoInfo wb
= wbList.get(position);
if(wb!=null){
convertView.setTag(wb.getId());
wh.wbuser.setText(wb.getUserName());
wh.wbtime.setText(wb.getTime());
wh.wbtext.setText(wb.getText(), TextView.BufferType.SPANNABLE);
textHighlight(wh.wbtext,
new char[]{#},new char[]{#});
textHighlight(wh.wbtext,
new char[]{@},new char[]{:, });
textHighlight2(wh.wbtext,
http://, );

if(wb.getHaveImage()){
wh.wbimage.setImageResource(R.drawable.images);
}
Drawable cachedImage
= asyncImageLoader.loadDrawable(wb.getUserIcon(),wh.wbicon, new ImageCallback(){

@Override
public void imageLoaded(Drawable imageDrawable,ImageView imageView, String imageUrl) {
imageView.setImageDrawable(imageDrawable);
}

});
if (cachedImage == null) {
wh.wbicon.setImageResource(R.drawable.usericon);
}
else{
wh.wbicon.setImageDrawable(cachedImage);
}
}

return convertView;
}

上面的这个Adapter实现没有什么特别的很普通,不过这个中使用了AsyncImageLoader的方法,这个是用来实现用户头像图标的异步载入显示,这样能提高列表显示的速度,提高用户体验,AsyncImageLoader的代码如下:

代码

public class AsyncImageLoader {
//SoftReference是软引用,是为了更好的为了系统回收变量
private HashMap<String, SoftReference<Drawable>> imageCache;
public AsyncImageLoader() {
imageCache
= new HashMap<String, SoftReference<Drawable>>();
}

public Drawable loadDrawable(final String imageUrl,final ImageView imageView, final ImageCallback imageCallback){
if (imageCache.containsKey(imageUrl)) {
//从缓存中获取
SoftReference<Drawable> softReference = imageCache.get(imageUrl);
Drawable drawable
= softReference.get();
if (drawable != null) {
return drawable;
}
}
final Handler handler = new Handler() {
public void handleMessage(Message message) {
imageCallback.imageLoaded((Drawable) message.obj, imageView,imageUrl);
}
};
//建立新一个新的线程下载图片
new Thread() {
@Override
public void run() {
Drawable drawable
= loadImageFromUrl(imageUrl);
imageCache.put(imageUrl,
new SoftReference<Drawable>(drawable));
Message message
= handler.obtainMessage(0, drawable);
handler.sendMessage(message);
}
}.start();
return null;
}

public static Drawable loadImageFromUrl(String url){
URL m;
InputStream i
= null;
try {
m
= new URL(url);
i
= (InputStream) m.getContent();
}
catch (MalformedURLException e1) {
e1.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
Drawable d
= Drawable.createFromStream(i, src);
return d;
}

//回调接口
public interface ImageCallback {
public void imageLoaded(Drawable imageDrawable,ImageView imageView, String imageUrl);
}
}

完成上述的工作后,接下来就是显示微薄列表, 在HomeActivity的onCreate方法中调用loadList();代码如下:

代码

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);

。。。。。。
loadList();
}

private void loadList(){
if(ConfigHelper.nowUser==null)
{

}
else
{
user
=ConfigHelper.nowUser;
//显示当前用户名称
TextView showName=(TextView)findViewById(R.id.showName);
showName.setText(user.getUserName());

OAuth auth=new OAuth();
String url
= http://api.t.sina.com.cn/statuses/friends_timeline.json;
List params
=new ArrayList();
params.add(
new BasicNameValuePair(source, auth.consumerKey));
HttpResponse response
=auth.SignRequest(user.getToken(), user.getTokenSecret(), url, params);
if (200 == response.getStatusLine().getStatusCode()){
try {
InputStream is
= response.getEntity().getContent();
Reader reader
= new BufferedReader(new InputStreamReader(is), 4000);
StringBuilder buffer
= new StringBuilder((int) response.getEntity().getContentLength());
try {
char[] tmp = new char[1024];
int l;
while ((l = reader.read(tmp)) != 1) {
buffer.append(tmp,
0, l);
}
}
finally {
reader.close();
}
String string
= buffer.toString();
//Log.e(“json”, “rs:” + string);
response.getEntity().consumeContent();
JSONArray data
=new JSONArray(string);
for(int i=0;i<data.length();i++)
{
JSONObject d
=data.getJSONObject(i);
//Log.e(“json”, “rs:” + d.getString(“created_at”));
if(d!=null){
JSONObject u
=d.getJSONObject(user);
if(d.has(retweeted_status)){
JSONObject r
=d.getJSONObject(retweeted_status);
}

//微博id
String id=d.getString(id);
String userId
=u.getString(id);
String userName
=u.getString(screen_name);
String userIcon
=u.getString(profile_image_url);
Log.e(
userIcon, userIcon);
String time
=d.getString(created_at);
String text
=d.getString(text);
Boolean haveImg
=false;
if(d.has(thumbnail_pic)){
haveImg
=true;
//String thumbnail_pic=d.getString(“thumbnail_pic”);
//Log.e(“thumbnail_pic”, thumbnail_pic);
}

Date date=new Date(time);
time
=ConvertTime(date);
if(wbList==null){
wbList
=new ArrayList<WeiBoInfo>();
}
WeiBoInfo w
=new WeiBoInfo();
w.setId(id);
w.setUserId(userId);
w.setUserName(userName);
w.setTime(time);
w.setText(text);

w.setHaveImage(haveImg);
w.setUserIcon(userIcon);
wbList.add(w);
}
}

}catch (IllegalStateException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (JSONException e) {
e.printStackTrace();
}
}

if(wbList!=null)
{
WeiBoAdapater adapater
= new WeiBoAdapater();
ListView Msglist
=(ListView)findViewById(R.id.Msglist);
Msglist.setOnItemClickListener(
new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> arg0, View view,int arg2, long arg3) {
Object obj
=view.getTag();
if(obj!=null){
String id
=obj.toString();
Intent intent
= new Intent(HomeActivity.this,ViewActivity.class);
Bundle b
=new Bundle();
b.putString(
key, id);
intent.putExtras(b);
startActivity(intent);
}
}

});
Msglist.setAdapter(adapater);
}
}
loadingLayout.setVisibility(View.GONE);
}

上面的loadList() 方法通过新浪Api接口http://api.t.sina.com.cn/statuses/friends_timeline.json获取当前登录用户及其所关注用户的最新微博消息,然后显示到列表中。

这样就完成了用户首页功能的开发。

[原创]获得Android系统的root权限

mikel阅读(956)

刚买了款中兴 X876的Android2.1的手机,发现不少联通绑定的功能很是烦人,动不动开机就自动启动,既占内存又影响使用,找个软件要半天!于是想卸载,发现联通真的做的很绝,居然卸载不了,居然是系统应用,这可怎么办?!

于是去Android相关网站逛了逛,发现款可以获得root权限的软件:

一键root 1.6 推荐给大家

下载地址:点击下载

软件简介:

想要Root吗?想到要抓不知道内容是什么的映像档,想到还要找记忆卡作Gold Card,再想到还要进工程模式,为的就是要取得Root权限(但取得Root跟刷ROM是两回事,只是刷好的ROM刚好开了Root权限而已),现在,似乎可以不用这么麻烦。天下没有没有漏洞的OS,就跟不会有没bug的程序一样,前阵子有人通过iOS的PDF漏洞成功JB,而Android自然也有漏洞,以便取得Root权限。这个程序叫做 “Universal Androot” ,便是把exploit走后门的流程写出UI形式,让使用者只要按一下按钮就可以Root,只是不是什么每支Android手机都可以成功,像 Samsung i9000就没办法,这是由台湾人写出来的,请大家多多测试,并帮忙回报。如果担心会破坏保修,可以按下 “UnRoot” ,就可回复原有的状态。使用机型列表: Google Nexus One (2.2) HTC Hero (2.1) HTC Magic (1.5) Dell Streak (2.1) Motorola Milestone (2.1) Motorola XT701 Motorola XT800 (2.1) Motorola ME511 Sony Ericsson X10 (1.6) Sony Ericsson X10 Mini Pro (1.6) Acer Liquid (2.1) Vibo A688 (1.6) 无法使用列表: Samsung i9000 (Galaxy S) Samsung i6500U HuaWei U8220 HTC Desire / Legend / Wildfire (/system 無法寫入) 这款一键RootUniversal Androot软件market里面还没有噢!因为太新了。如果想root的朋友看看自己的机型在不在可以使用的列表里面.