首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

Cassandra概念学习系列之Cassandra是什么?

不多说,直接上干货! http://cassandra.apache.org/ Apache Cassandra是一套开源分布式NoSQL数据库系统。它最初由Facebook开发,用于储存收件箱等简单格式数据,集Google BigTable的数据模型与Amazon Dynamo的完全分布式的架构于一身。Facebook于2008将 Cassandra 开源,此后,由于Cassandra良好的可扩放性,被Digg、Twitter等知名Web 2.0网站所采纳,成为了一种流行的分布式结构化数据存储方案。 它是一个开源的、分布式、无中心、支持水平扩展、高可用的KEY-VALUE类型的NOSQL数据库。 官网文档地址是在:http://cassandra.apache.org/doc/latest/ 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/8031459.html如需转载请自行联系原作者

优秀的个人博客,低调大师

ABP架构学习系列三:手工搭建ABP框架

由于公司的项目才接触到ABP这个框架,当时就觉得高大上,什么IOC、AOP、ddd各种专业词汇让人激情 澎湃,但在使用过程中碰到了许多坑,可能也许是没有去看源码导致的,但工作确实没有那么多时间让人去慢慢研究。很久之前想手动搭建这个框架了,但是各种理由,你懂的。但是要在技术上得到大的提升就得静的下心去研究,学到大神的思想和精髓,运用到实际中去,才能去体验更开阔的天地。 本文以创建博客为思路,一步步构建整个项目,在摸索中进步,也希望能够帮助到有需要的人。 一、基础架构 第一部分主要是搭建好整个项目的骨架,连通各个项目 创建MVC5项目(ZmBlog.Web),手动引入Abp、Abp.Web、Abp.Web.Mvc、Abp.Web.Api 详情请看上一篇第一部分: http://www.cnblogs.com/xcsn/p/7941541.html 接下来,继续创建其他类库ZmBlog.Core、ZmBlog.Infrastructure、ZmBlog.Application。 引入相关nuget包,所有项目引用abp,ZmBlog.Infrastructure引用 Abp.EntityFramework,web项目引用后两个 Install-Package Abp -Version 0.8.4 Install-Package Abp.EntityFramework -Version 0.8.4 Install-Package Abp.Web.Mvc -Version 0.8.4 Install-Package Abp.Web.Api -Version 0.8.4 二、ZmBlog.Core ZmBlog.Core是DDD的核心,实体、领域服务、事件等一般都写在这里,同时也定义了仓储的接口,但实现放在基础设施层。 首先,添加类ZmBlogCoreModule,如下 namespace ZmBlog.Core { public class ZmBlogCoreModule:AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } } ZmBlogCoreModule必须依赖于AbpModule,ZmBlogCoreModule是自定义模块第一个启动的,另外,ZmBlogCoreModule启动之前,abp会先启用内部的AbpKernelModule。 AbpKernelModule类是Abp框架自己的Module,它也跟所有其他的Module一样继承自AbpModule,重写PreInitialize,Initialize,PostInitialize三个主要成员。 更详细的请参考:https://www.cnblogs.com/Azula/archive/2015/11/23/4989157.html 现在,定义一个实体文章分类Category,继承自Entity<TPrimaryKey> public class Category: Entity<string> { public Category() { Id = Guid.NewGuid().ToString(); } /// <summary> /// 类别名称 /// </summary> public string Name { get; set; } /// <summary> /// 状态(0隐藏1显示) /// </summary> public int Status { get; set; } } 以下是Entity<TPrimaryKey>的成员,其中定义了主键Id(可重写) 接着,添加一个仓储接口ICategoryRepository public interface ICategoryRepository : IRepository<Category,string>{} 另外,还可以添加领域服务ICategoryDomainService、CategoryDomainService,对于业务简单的模块,可以去掉领域服务,直接在应用层处理。 public interface ICategoryDomainService:IDomainService{} public class CategoryDomainService : DomainService, ICategoryDomainService{} 三、ZmBlog.Infrastructure 1.定义模块 创建一个模块ZmBlogDataModule,依赖模块AbpEntityFrameworkModule会自动注册了所有仓储接口 [DependsOn(typeof(ZmBlogCoreModule),typeof(AbpEntityFrameworkModule))] public class ZmBlogDataModule : AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } 2.使用EF作为orm 使用以下命令引入包 Install-Package EntityFramework -Version 6.1.3 Install-Package Castle.Windsor -Version 3.3.0 (1)创建ZmBlogDbContext public class ZmBlogDbContext: AbpDbContext { public ZmBlogDbContext() : base("DefaultConnection") { } public ZmBlogDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { } //This constructor is used in tests public ZmBlogDbContext(DbConnection connection) : base(connection, true) { } public DbSet<Category> Categorys { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); modelBuilder.Configurations.Add(new CategoryCfg());//使用独立配置 } } DefaultConnection是连接字符串名称,在web项目添加或修改如下 <connectionStrings> <add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog=ZmBlogDb;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings> CategoryCfg是对实体类型的配置,如设置Id为主键 public class CategoryCfg: EntityTypeConfiguration<Category> { public CategoryCfg() { HasKey(s => s.Id); } } (2)使用codefirst模式 1.启用迁移 启用:Enable-Migrations 自动生成配置文件:Configuration.cs 2.创建迁移 add-migration AddCategory 自动生成迁移文件:201712040256502_AddCategory 3.执行迁移 update-database -vebose 自动生成数据库ZmBlogDb、迁移记录表__MigrationHistory、表Categories (3)实现仓储 基础类BaseRepository,继承实现增删改查 public abstract class BaseRepository<TEntity, TPrimaryKey> :EfRepositoryBase<ZmBlogDbContext,TEntity,TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey> { protected BaseRepository(IDbContextProvider<ZmBlogDbContext> dbContextProvider) : base(dbContextProvider) { } //add common methods for all repositories } public abstract class BaseRepository<TEntity> : BaseRepository<TEntity, string> where TEntity : class, IEntity<string> { protected BaseRepository(IDbContextProvider<ZmBlogDbContext> dbContextProvider) : base(dbContextProvider) { } //do not add any method here, add to the class above (since this inherits it) } 自定义的实现类,如下 public class CategoryRepository : BaseRepository<Category, string>, ICategoryRepository { public CategoryRepository(IDbContextProvider<ZmBlogDbContext> dbContextProvider) : base(dbContextProvider) { } } 四、ZmBlog.Application 1.添加模块 添加模块ZmBlogApplicationModule namespace ZmBlog.Application { [DependsOn(typeof(ZmBlogCoreModule), typeof(ZmBlogDataModule))] public class ZmBlogApplicationModule:AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } } 2.创建服务 在项目下添加文件夹Categories,然后添加服务接口和实现类,如 ICategoryApp public interface ICategoryApp:IApplicationService { string GetCategoryName(string id); } CategoryApp namespace ZmBlog.Application.Categories { public class CategoryApp : ApplicationService, ICategoryApp { private readonly IRepository<Category, string> _categoryRepository; public CategoryApp(IRepository<Category, string> categoryRepository) { _categoryRepository = categoryRepository; } //private readonly ICategoryRepository _categoryRepository; //public CategoryApp(ICategoryRepository categoryRepository) //{ // _categoryRepository = categoryRepository; //} public string GetCategoryName(string id) { //var categoryData = _categoryRepository.GetAll().FirstOrDefault(s=>s.Name == "硬件"); var category = new Category() { Name = "硬件" + DateTime.Now.ToString("yy-MM-dd HH:mm:ss"), Status = 1 }; _categoryRepository.Insert(category); CurrentUnitOfWork.SaveChanges(); return category.Name; } } } 五、ZmBlog.Web修改 1.增加依赖 ZmBlogWebModule是web的模块,上一篇文章创建的,增加依赖ZmBlogApplicationModule [DependsOn(typeof(AbpWebMvcModule),typeof(ZmBlogApplicationModule))] public class ZmBlogWebModule:AbpModule { //... } 2.修改控制器 public class HomeController : AbpController { private ICategoryApp _categoryApp; public HomeController(ICategoryApp categoryApp) { _categoryApp = categoryApp; } public ActionResult Index() { try { ViewBag.Name = _categoryApp.GetCategoryName(""); } catch (Exception e) { ViewBag.Name = "默认分类"; throw; } return View(); } //.....省略 3.页面修改 @{ ViewBag.Title = "Home Page"; } <div class="jumbotron"> <h1>I Like @ViewBag.Name</h1> </div> 去掉没用的,直接展示效果 六、展示 运行起来的效果 数据库 由于时间原因,一些细节没有详细讲,如有不清楚请留言 源码下载:https://github.com/jackchn/cnblogs-xcsn-source下的ZmBlogStudy.rar

优秀的个人博客,低调大师

Centos 5.8 安装KVM虚拟机学习笔记

KVM虚拟机简介 KVM(Kernel-based Virtual Machine)的简称,是一个开源的全虚拟化的解决方案。自从Linux2.6.20之后集成在Linux的各个发行版中,KVM虚拟化运行在x86架构且需要硬件(Intel VT or AMD-V)的支持,它使用Linux自身的调度器进行管理,下面是在centos5.8上面详细安装Kvm虚拟机的详细步骤。 1.查看宿主机的cpu是否支持KVM,vmx表示CPU支持Intel VT技术,svm代表CPU支持AMD-v技术。 2.安装KVM软件包,yum groupinstall KVM。 3.安装桥接管理工具,yum install bridge-utils tunctl。 4.设置桥接网卡配置文件,先备份一下原来的配置文件。 4.1编辑ifcfg-eth0文件。 4.2编辑ifcfg-br0文件。 5.安装gui管理工具,yum install virt-manager virt-viewer。 6.1查看服务器的配置是否生效,KVM安装完成后需要重启(reboot)服务器后才能被内核加载。 6.2查看桥接网卡配置是否生效。 6.3查看内核是否加载KVM模块。 7.在服务器上面安装vncserver,以便通过vncerver来安装虚拟机。 7.1VNC环境需要安装KDE或者GNOME环境,生产环境的服务器都采用最小化安装,用yum grouplist可以查看系统安装了那些组件,这里安装KDE环境。 7.2安装vnc_server,yum install vnc-server。 7.3运行vncserver 添加客户端VNC登录需要的密码。 7.4修改配置文件/root/.vnc/xstartup,startkde &表示支持KDE组件。 7.5修改vncserver 配置文件/etc/sysconfig/vncservers,添加如下两行。 7.6重启VNC服务,/etc/init.d/vncserver restart。 8.1客户端用VNC_viewer连接到服务器,在开始-System-terminal开启终端,输入virt-manager调出虚拟系统管理器新建虚拟机。 8.2KVM支持全虚拟化,选择CPU架构和KVM管理程序。 8.3选择安装介质为本地ISO文件。 8.4选择ISO文件路径,此种方法要将ISO文件上传服务器上面。 8.5选择KVM虚拟机的磁盘空间,在新建虚拟机时候自动生成.img文件,可以用qemu-img创建。 8.6选择网络为共享的物理设备,即桥接。 8.7选择创建虚拟机的内存大小和虚拟cpu数。 8.8虚拟机创建完毕,后面安装系统部分省略了,和vmware安装虚拟机完全一致。 9)系统安装完毕以后,用virsh工具开启虚拟机。 10)然后通过VNC或者SSH可以远程管理虚拟机了。 总结:1)KVM虚拟机不仅需要CPU的支持,还需要在BOIS里面开启VT选项。 2)在终端用virsh list可以查看当前正在运行的虚拟机。 3)在virsh #模式下面,可以用start 机器名开启虚拟机,用shutdown 虚拟机名关闭虚拟机。 4)创建虚拟机,virt-install --name TEST001 --ram 1024 --vcpus=2 --disk path=/data/vps/TEST001.img,size=20 --bridge=br0 --accelerate --cdrom /opt/iso/CentOS-5.8-x86_64-bin-DVD.iso --vnc --vncport=-1。 5)移除虚拟机virsh undefine TEST001。 附件:http://down.51cto.com/data/2361999 本文转自 sfzhang 51CTO博客,原文链接:http://blog.51cto.com/sfzhang88/1093720,如需转载请自行联系原作者

优秀的个人博客,低调大师

Storm概念学习系列之storm核心组件

Storm核心组件 了解 Storm 的核心组件对于理解 Storm 原理非常重要,下面介绍 Storm 的整体,然后介绍 Storm 的核心。 Storm 集群由一个主节点和多个工作节点组成。主节点运行一个名为“Nimbus”的守护进程,工作节点都运行一个名为“Supervisor”的守护进程,两者的协调工作由 ZooKeeper 来完成, ZooKeeper 用于管理集群中的不同组件。 每一个工作节点上运行的 Supervisor 监听分配给它那台机器的工作,根据需要启动 / 关闭工作进程,每一个工作进程执行一个 Topology 的一个子集;一个运行的 Topology 由运行在很多机器上的很多工作进程 Worker 组成。那么Storm 的核心就是主节点(Nimbus)、工作节点(Supervisor)、协调器(ZooKeeper)、工作进程( Worker)、任务线程(Task)。 1、主节点 Nimbus 主节点通常运行一个后台程序——Nimbus,用于响应分布在集群中的节点,分配任务和监测故障,这类似于 Hadoop 中的 JobTracker。 Nimbus 进程是快速失败( fail-fast)和无状态的,所有的状态要么在 ZooKeeper 中,要么在本地磁盘上。可以使用 kill -9 来杀死 Nimbus 进程,然后重启即可继续工作。 2、工作节点 Supervisor 工作节点同样会运行一个后台程序——Supervisor,用于收听工作指派并基于要求运行工作进程。每个工作节点都是Topology中一个子集的实现。而Nimbus 和 Supervisor 之间的协调则通过 ZooKeeper 系统。同 样,Supervisor进程也是快速失败(fail-fast)和无状态的, 所有的状态要么在ZooKeeper中,要么在本地磁盘上,用kill -9来杀死Supervisor进程,然后重启就可以继续工作。 3、协调服务组件 ZooKeeper ZooKeeper 是完成 Nimbus 和 Supervisor 之间协调的服务。 Storm使用ZooKeeper 协调集群,由于ZooKeeper 并不用于消息传递,所以Storm给ZooKeeper 带来的压力相当低。在大多数情况下,单个节点的 ZooKeeper 集群足够胜任,不过为了确保故障恢复或者部署大规模Storm集群,可能需要更大规模的 ZooKeeper 集群。 Nimbus、 Supervisor 与 ZooKeeper 的关系如图 1 所示。 图 1 Nimbus、 Supervisor 与 ZooKeeper 关系图 4、其他核心组件 Storm 的组件不止上面的,还有一些组件也是 Storm 的核心,缺一不可。下面简单介绍Worker 和 Task。 1)具体处理事务进程 Worker:运行具体处理组件逻辑的进程。 2)具体处理线程 Task:Worker 中的每一个 Spout/Bolt 线程称为一个 Task。在 Storm 0.8之后,Task 不再与物理线程对应,同一个 Spout/Bolt 的 Task 可能会共享一个物理线程,该线程称为 Executor。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5989256.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发学习笔记:BroadcastReceiver简介和注册方式

一.BroadcastReceiver简介 BraodcastReceiver(广播接收器)是为了实现系统广播而提供的一种组件,它和事件处理机制类似,但是事件处理机制是程序组件级别的,而广播事件处理机制是系统级别的。比如,我们可以发出一种广播来测试手机电量的变化,这时候就可以定义一个BraodcastReceiver来接受广播,当手机电量较低时提示用户。我们既可以用Intent来启动一个组件,也可以用sendBroadcast()方法发起一个系统级别的事件广播来传递消息。我们同样可以在自己的应用程序中实现BroadcastReceiver来监听和响应广播的Intent。 在程序中使用BraodcastReceiver是比较简单的。首先要定义一个类继承BraodcastReceiver,并且覆盖onReceiver()方法来响应事件。然后注册在程序中BraodcastReceiver。最后构建Intent对象调用sendBroadcast()方法将广播发出。 二.BroadcastReceiver的注册方式 1.静态注册方式 静态注册方式是在AndroidManifest.xml的application里面定义receiver并设置要接收的action。静态注册方式的特点:不管改应用程序是否处于活动状态,都会进行监听,比如某个程序时监听 下面是具体的例子: MainActivity.java packagecom.android.broadcast; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ //定义action常量 protectedstaticfinalStringACTION="com.android.broadcast.RECEIVER_ACTION"; //定义Button对象 privateButtonbtnBroadcast; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); btnBroadcast=(Button)findViewById(R.id.btnBroadcast); //为按钮设置单击监听器 btnBroadcast.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //实例化Intent Intentintent=newIntent(); //设置Intent的action属性 intent.setAction(ACTION); //发出广播 sendBroadcast(intent); } }); } } 在“com.android.broadcast”包中定义一个MyReceiver类,继承于BroadcastReceiver,覆盖onReceive()方法。 MyReceiver.java packagecom.android.broadcast; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.util.Log; publicclassMyReceiverextendsBroadcastReceiver{ //定义日志标签 privatestaticfinalStringTAG="Test"; @Override publicvoidonReceive(Contextcontext,Intentintent){ //输出日志信息 Log.i(TAG,"MyReceiveronReceive--->"); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/btnBroadcast" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送Broadcast" /> </LinearLayout> 在AndroidManifest.xml配置文件中16~20行声明receiver <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.broadcast" android:versionCode="1" android:versionName="1.0"> <uses-sdkandroid:minSdkVersion="10"/> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <receiverandroid:name="MyReceiver"> <intent-filter> <actionandroid:name="com.android.broadcast.RECEIVER_ACTION"/> </intent-filter> </receiver> </application> </manifest> 效果图: 当我们点击按钮的时候,程序会调用onReceive()方法,LogCat输出信息如下: 2.动态注册方式 动态注册方式在activity里面调用函数来注册,和静态的内容差不多。一个形参是receiver,另一个是IntentFilter,其中里面是要接收的action。动态注册方式特点:在代码中进行注册后,当应用程序关闭后,就不再进行监听。 下面是具体的例子: MainActivity.java packagecom.android.broadcast; importandroid.app.Activity; importandroid.content.Intent; importandroid.content.IntentFilter; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ //定义Action常量 protectedstaticfinalStringACTION="com.android.broadcast.RECEIVER_ACTION"; privateButtonbtnBroadcast; privateButtonregisterReceiver; privateButtonunregisterReceiver; privateMyReceiverreceiver; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); btnBroadcast=(Button)findViewById(R.id.btnBroadcast); //创建事件监听器 btnBroadcast.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ Intentintent=newIntent(); intent.setAction(ACTION); sendBroadcast(intent); } }); registerReceiver=(Button)findViewById(R.id.btnregisterReceiver); //创建事件监听器 registerReceiver.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ receiver=newMyReceiver(); IntentFilterfilter=newIntentFilter(); filter.addAction(ACTION); //动态注册BroadcastReceiver registerReceiver(receiver,filter); } }); unregisterReceiver=(Button)findViewById(R.id.btnunregisterReceiver); //创建事件监听器 unregisterReceiver.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //注销BroadcastReceiver unregisterReceiver(receiver); } }); } } 在“com.android.broadcast”包中定义一个MyReceiver类,继承于BroadcastReceiver,覆盖onReceive()方法。 MyReceiver.java packagecom.android.broadcast; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.util.Log; publicclassMyReceiverextendsBroadcastReceiver{ //定义日志标签 privatestaticfinalStringTAG="Test"; @Override publicvoidonReceive(Contextcontext,Intentintent){ //输出日志信息 Log.i(TAG,"MyReceiveronReceive--->"); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/btnBroadcast" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送广播" /> <Button android:id="@+id/btnregisterReceiver" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注册广播接收器" /> <Button android:id="@+id/btnunregisterReceiver" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注销广播接听器" /> </LinearLayout> 效果图: ①当我们首先点击按钮的时候,因为程序没有注册BraodcastReceiver,所以LogCat没有输出任何信息。 ②当我们先点击再点击按钮的时候,这时程序会动态的注册BraodcastReceiver,之后会调用onReceive()方法,LogCat输出信息如下: ③当我们点击按钮的时候,这时程序会注销BraodcastReceiver,再点击,LogCat没有输出任何信息。 三.BroadcastReceiver的生命周期 一个BroadcastReceiver 对象只有在被调用onReceive(Context, Intent)的才有效的,当从该函数返回后,该对象就无效的了,结束生命周期。 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/655885

优秀的个人博客,低调大师

【Android进阶学习】shape和selector的结合使用

shape和selector是Android UI设计中经常用到的,比如我们要自定义一个圆角Button,点击Button有些效果的变化,就要用到shape和selector。可以这样说,shape和selector在美化控件中的作用是至关重要的。 1.Shape 简介 作用:XML中定义的几何形状 位置:res/drawable/文件的名称.xml 使用的方法: Java代码中:R.drawable.文件的名称 XML中:android:background="@drawable/文件的名称" 属性: <shape>android:shape=["rectangle" | "oval" | "line" | "ring"] 其中rectagle矩形,oval椭圆,line水平直线,ring环形 <shape>中子节点的常用属性: <gradient> 渐变 android:startColor 起始颜色 android:endColor 结束颜色 android:angle 渐变角度,0从上到下,90表示从左到右,数值为45的整数倍默认为0; android:type 渐变的样式 liner线性渐变 radial环形渐变 sweep <solid > 填充 android:color 填充的颜色 <stroke > 描边 android:width 描边的宽度 android:color 描边的颜色 android:dashWidth 表示'-'横线的宽度 android:dashGap 表示'-'横线之间的距离 <corners> 圆角 android:radius 圆角的半径 值越大角越圆 android:topRightRadius 右上圆角半径 android:bottomLeftRadius 右下圆角角半径 android:topLeftRadius 左上圆角半径 android:bottomRightRadius 左下圆角半径 2.Selector 简介 位置:res/drawable/文件的名称.xml 使用的方法: Java代码中:R.drawable.文件的名称 XML中:android:background="@drawable/文件的名称" <?xmlversion="1.0"encoding="utf-8"?> <selectorxmlns:android="http://schemas.android.com/apk/res/android"> <!--默认时的背景图片--> <itemandroid:drawable="@drawable/pic1"/> <!--没有焦点时的背景图片--> <item android:state_window_focused="false" android:drawable="@drawable/pic_blue" /> <!--非触摸模式下获得焦点并单击时的背景图片--> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/pic_red" /> <!--触摸模式下单击时的背景图片--> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/pic_pink" /> <!--选中时的图片背景--> <item android:state_selected="true" android:drawable="@drawable/pic_orange" /> <!--获得焦点时的图片背景--> <item android:state_focused="true" android:drawable="@drawable/pic_green" /> </selector> 第一个例子:圆角的Button http://liangruijun.blog.51cto.com/3061169/630051 第二个例子:shape+selector综合使用的例子 漂亮的ListView 先看看这个例子的结构: selector.xml <?xmlversion="1.0"encoding="utf-8"?> <selectorxmlns:android="http://schemas.android.com/apk/res/android"> <itemandroid:state_selected="true"> <shape> <gradientandroid:angle="270"android:endColor="#99BD4C" android:startColor="#A5D245"/> <sizeandroid:height="60dp"android:width="320dp"/> <cornersandroid:radius="8dp"/> </shape> </item> <itemandroid:state_pressed="true"> <shape> <gradientandroid:angle="270"android:endColor="#99BD4C" android:startColor="#A5D245"/> <sizeandroid:height="60dp"android:width="320dp"/> <cornersandroid:radius="8dp"/> </shape> </item> <item> <shape> <gradientandroid:angle="270"android:endColor="#A8C3B0" android:startColor="#C6CFCE"/> <sizeandroid:height="60dp"android:width="320dp"/> <cornersandroid:radius="8dp"/> </shape> </item> </selector> list_item.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/selector" > <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="20dp" /> <TextView android:text="data" android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:textSize="14sp" android:textStyle="bold" android:textColor="@color/black" > </TextView> </LinearLayout> main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#253853" > <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="#00000000" android:divider="#2A4562" android:dividerHeight="3px" android:listSelector="#264365" android:drawSelectorOnTop="false" > </ListView> </LinearLayout> colors.xml <?xmlversion="1.0"encoding="utf-8"?> <resources> <colorname="white">#FFFFFFFF</color> <colorname="transparency">#00000000</color> <colorname="title_bg">#1C86EE</color> <colorname="end_color">#A0cfef83</color> <colorname="black">#464646</color> </resources> MainActivity.xml packagecom.lingdududu.customlist; importjava.util.ArrayList; importjava.util.HashMap; importxb.customlist.R; importandroid.R.array; importandroid.app.Activity; importandroid.os.Bundle; importandroid.widget.ArrayAdapter; importandroid.widget.ListView; importandroid.widget.SimpleAdapter; publicclassMainActivityextendsActivity{ ListViewlist; Stringdata[]=newString[]{ "China","UK","USA","Japan","German","Canada","ET","Narotu" }; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); list=(ListView)findViewById(R.id.list); SimpleAdapteradapter=newSimpleAdapter(this,getData(),R.layout.list_item, newString[]{"title","img"},newint[]{R.id.title,R.id.img}); list.setAdapter(adapter); } privateArrayList<HashMap<String,Object>>getData(){ ArrayList<HashMap<String,Object>>dlist=newArrayList<HashMap<String,Object>>(); for(inti=0;i<data.length;i++){ HashMap<String,Object>map=newHashMap<String,Object>(); map.put("title",data[i]); map.put("img",R.drawable.item_left2); dlist.add(map); } returndlist; } } 效果图: 上面的例子中用到很多关于颜色RGB的参数,对RGB不熟悉的,可以参照我博客的一篇文章 http://liangruijun.blog.51cto.com/3061169/629276 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/732310

优秀的个人博客,低调大师

Android开发学习笔记:数据存取之SQLite浅析

一.SQLite的介绍 1.SQLite简介 SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入 式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持 Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl、PHP、Java、C++、.Net等,还有ODBC接口,同样比起 Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。 2.SQLite的特点: 轻量级 SQLite和C/S模式的数据库软件不同,它是进程内的数据库引擎,因此不存在数据库的客户端和服务器。使用SQLite一般只需要带上它的一个动态 库,就可以享受它的全部功能。而且那个动态库的尺寸也挺小,以版本3.6.11为例,Windows下487KB、Linux下347KB。 不需要"安装" SQLite的核心引擎本身不依赖第三方的软件,使用它也不需要"安装"。有点类似那种绿色软件。 单一文件 数据库中所有的信息(比如表、视图等)都包含在一个文件内。这个文件可以自由复制到其它目录或其它机器上。 跨平台/可移植性 除了主流操作系统 windows,linux之后,SQLite还支持其它一些不常用的操作系统。 弱类型的字段 同一列中的数据可以是不同类型 开源 这个相信大家都懂的! 3.SQLite数据类型 一般数据采用的固定的静态数据类型,而SQLite采用的是动态数据类型,会根据存入值自动判断。SQLite具有以下五种常用的数据类型: NULL: 这个值为空值 VARCHAR(n):长度不固定且其最大长度为 n 的字串,n不能超过 4000。 CHAR(n):长度固定为n的字串,n不能超过 254。 INTEGER: 值被标识为整数,依据值的大小可以依次被存储为1,2,3,4,5,6,7,8. REAL: 所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号. TEXT: 值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE). BLOB: 值是BLOB数据块,以输入的数据格式进行存储。如何输入就如何存储,不改 变格式。 DATA :包含了 年份、月份、日期。 TIME:包含了 小时、分钟、秒。 相信学过数据库的童鞋对这些数据类型都不陌生的!!!!!!!!!! 二.SQLiteDatabase的介绍 Android提供了创建和是用SQLite数据库的API。SQLiteDatabase代表一个数据库对象,提供了操作数据库的一些方法。在Android的SDK目录下有sqlite3工具,我们可以利用它创建数据库、创建表和执行一些SQL语句。下面是SQLiteDatabase的常用方法。 SQLiteDatabase的常用方法 方法名称 方法描述 openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory) 打开或创建数据库 insert(String table,String nullColumnHack,ContentValues values) 添加一条记录 delete(String table,String whereClause,String[] whereArgs) 删除一条记录 query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy) 查询一条记录 update(String table,ContentValues values,String whereClause,String[] whereArgs) 修改记录 execSQL(String sql) 执行一条SQL语句 close() 关闭数据库 1、打开或者创建数据库 在Android 中以使用SQLiteDatabase的静态方法openOrCreateDatabase(String path,SQLiteDatabae.CursorFactory factory)打开或者创建一个数据库。它会自动去检测是否存在这个数据库,如果存在则打开,不存在则创建一个数据库;创建成功则返回一个SQLiteDatabase对象,否则抛出异常FileNotFoundException。 下面是创建名为“stu.db”数据库的代码: db=SQLiteDatabase.openOrCreateDatabase("/data/data/com.lingdududu.db/databases/stu.db",null); 2、创建表 创建一张表很简单。首先,编写创建表的SQL语句,然后,调用SQLiteDatabase的execSQL()方法来执行SQL语句便可以创建一张表了。 下面的代码创建了一张用户表,属性列为:_id(主键并且自动增加)、sname(学生姓名)、snumber(学号) privatevoidcreateTable(SQLiteDatabasedb){ //创建表SQL语句 Stringstu_table="createtableusertable(_idintegerprimarykeyautoincrement,snametext,snumbertext)"; //执行SQL语句 db.execSQL(stu_table); } 3、插入数据 插入数据有两种方法: ①SQLiteDatabase的insert(String table,String nullColumnHack,ContentValues values)方法,参数一是表名称,参数二是空列的默认值,参数三是ContentValues类型的一个封装了列名称和列值的Map; ②编写插入数据的SQL语句,直接调用SQLiteDatabase的execSQL()方法来执行 第一种方法的代码: privatevoidinsert(SQLiteDatabasedb){ //实例化常量值 ContentValuescValue=newContentValues(); //添加用户名 cValue.put("sname","xiaoming"); //添加密码 cValue.put("snumber","01005"); //调用insert()方法插入数据 db.insert("stu_table",null,cValue); } 第二种方法的代码: privatevoidinsert(SQLiteDatabasedb){ //插入数据SQL语句 Stringstu_sql="insertintostu_table(sname,snumber)values('xiaoming','01005')"; //执行SQL语句 db.execSQL(sql); } 4、删除数据 删除数据也有两种方法: ①调用SQLiteDatabase的delete(String table,String whereClause,String[] whereArgs)方法,参数一是表名称,参数二是删除条件,参数三是删除条件值数组; ②编写删除SQL语句,调用SQLiteDatabase的execSQL()方法来执行删除。 第一种方法的代码: privatevoiddelete(SQLiteDatabasedb){ //删除条件 StringwhereClause="_id=?"; //删除条件参数 String[]whereArgs={String.valueOf(2)}; //执行删除 db.delete("stu_table",whereClause,whereArgs); } 第二种方法的代码: privatevoiddelete(SQLiteDatabasedb){ //删除SQL语句 Stringsql="deletefromstu_tablewhere_id=6"; //执行SQL语句 db.execSQL(sql); } 5、修改数据 修改数据有两种方法: ①调用SQLiteDatabase的update(String table,ContentValues values,String whereClause, String[] whereArgs)方法。参数是表名称,参数是更行列ContentValues类型的键值对(Map),参数是更新条件(where字句),参数是更新条件数组。 ②编写更新的SQL语句,调用SQLiteDatabase的execSQL执行更新。 第一种方法的代码: privatevoidupdate(SQLiteDatabasedb){ //实例化内容值 ContentValuesvalues=newContentValues(); //在values中添加内容 values.put("snumber","101003"); //修改条件 StringwhereClause="id=?"; //修改添加参数 String[]whereArgs={String.valuesOf(1)}; //修改 db.update("usertable",values,whereClause,whereArgs); } 第二种方法的代码: privatevoidupdate(SQLiteDatabasedb){ //修改SQL语句 Stringsql="updatestu_tablesetsnumber=654321whereid=1"; //执行SQL db.execSQL(sql); } 6、查询数据 在Android中查询数据是通过Cursor类来实现的,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。它提供了很多有关查询的方法,具体方法如下: public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy,String limit); 各个参数的意义说明: ①table:表名称 ②columns:列名称数组 ③selection:条件字句,相当于where ④selectionArgs:条件字句,参数数组 ⑤groupBy:分组列 ⑥having:分组条件 ⑦orderBy:排序列 ⑧limit:分页查询限制 ⑨Cursor:返回值,相当于结果集ResultSet Cursor是一个游标接口,提供了遍历查询结果的方法,如移动指针方法move(),获得列值方法getString()等. Cursor游标常用方法 方法名称 方法描述 getCount() 获得总的数据项数 isFirst() 判断是否第一条记录 isLast() 判断是否最后一条记录 moveToFirst() 移动到第一条记录 moveToLast() 移动到最后一条记录 move(int offset) 移动到指定记录 moveToNext() 移动到下一条记录 moveToPrevious() 移动到上一条记录 getColumnIndexOrThrow(String columnName) 根据列名称获得列索引 getInt(int columnIndex) 获得指定列索引的int类型值 getString(int columnIndex) 获得指定列缩影的String类型值 下面就是用Cursor来查询数据库中的数据,具体代码如下: privatevoidquery(SQLiteDatabasedb) { //查询获得游标 Cursorcursor=db.query("usertable",null,null,null,null,null,null); //判断游标是否为空 if(cursor.moveToFirst(){ //遍历游标 for(inti=0;i<cursor.getCount();i++){ cursor.move(i); //获得ID intid=cursor.getInt(0); //获得用户名 Stringusername=cursor.getString(1); //获得密码 Stringpassword=cursor.getString(2); //输出用户信息 System.out.println(id+":"+sname+":"+snumber); } } } 7、删除指定表 编写插入数据的SQL语句,直接调用SQLiteDatabase的execSQL()方法来执行 privatevoiddrop(SQLiteDatabasedb){ //删除表的SQL语句 Stringsql="DROPTABLEstu_table"; //执行SQL db.execSQL(sql); } 三.SQLiteOpenHelper 该类是SQLiteDatabase一个辅助类。这个类主要生成一 个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的方法getWritableDatabase()或者 getReadableDatabase()方法的时候,如果当时没有数据,那么Android系统就会自动生成一个数据库。 SQLiteOpenHelper 是一个抽象类,我们通常需要继承它,并且实现里面的3个函数: 1.onCreate(SQLiteDatabase) 在数据库第一次生成的时候会调用这个方法,也就是说,只有在创建数据库的时候才会调用,当然也有一些其它的情况,一般我们在这个方法里边生成数据库表。 2. onUpgrade(SQLiteDatabase,int,int) 当数据库需要升级的时候,Android系统会主动的调用这个方法。一般我们在这个方法里边删除数据表,并建立新的数据表,当然是否还需要做其他的操作,完全取决于应用的需求。 3. onOpen(SQLiteDatabase): 这是当打开数据库时的回调函数,一般在程序中不是很常使用。 写了这么多,改改用实际例子来说明上面的内容了。下面这个操作数据库的实例实现了创建数据库,创建表以及数据库的增删改查的操作。 SQLiteActivity.java packagecom.lingdududu.testSQLite; importcom.lingdududu.testSQLiteDb.StuDBHelper; importandroid.app.Activity; importandroid.content.ContentValues; importandroid.database.Cursor; importandroid.database.sqlite.SQLiteDatabase; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; /* *@authorlingdududu */ publicclassSQLiteActivityextendsActivity{ /**Calledwhentheactivityisfirstcreated.*/ //声明各个按钮 privateButtoncreateBtn; privateButtoninsertBtn; privateButtonupdateBtn; privateButtonqueryBtn; privateButtondeleteBtn; privateButtonModifyBtn; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //调用creatView方法 creatView(); //setListener方法 setListener(); } //通过findViewById获得Button对象的方法 privatevoidcreatView(){ createBtn=(Button)findViewById(R.id.createDatabase); updateBtn=(Button)findViewById(R.id.updateDatabase); insertBtn=(Button)findViewById(R.id.insert); ModifyBtn=(Button)findViewById(R.id.update); queryBtn=(Button)findViewById(R.id.query); deleteBtn=(Button)findViewById(R.id.delete); } //为按钮注册监听的方法 privatevoidsetListener(){ createBtn.setOnClickListener(newCreateListener()); updateBtn.setOnClickListener(newUpdateListener()); insertBtn.setOnClickListener(newInsertListener()); ModifyBtn.setOnClickListener(newModifyListener()); queryBtn.setOnClickListener(newQueryListener()); deleteBtn.setOnClickListener(newDeleteListener()); } //创建数据库的方法 classCreateListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ //创建StuDBHelper对象 StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可读的SQLiteDatabase对象 SQLiteDatabasedb=dbHelper.getReadableDatabase(); } } //更新数据库的方法 classUpdateListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ //数据库版本的更新,由原来的1变为2 StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,2); SQLiteDatabasedb=dbHelper.getReadableDatabase(); } } //插入数据的方法 classInsertListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可写的数据库 SQLiteDatabasedb=dbHelper.getWritableDatabase(); //生成ContentValues对象//key:列名,value:想插入的值 ContentValuescv=newContentValues(); //往ContentValues对象存放数据,键-值对模式 cv.put("id",1); cv.put("sname","xiaoming"); cv.put("sage",21); cv.put("ssex","male"); //调用insert方法,将数据插入数据库 db.insert("stu_table",null,cv); //关闭数据库 db.close(); } } //查询数据的方法 classQueryListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可写的数据库 SQLiteDatabasedb=dbHelper.getReadableDatabase(); //参数1:表名 //参数2:要想显示的列 //参数3:where子句 //参数4:where子句对应的条件值 //参数5:分组方式 //参数6:having条件 //参数7:排序方式 Cursorcursor=db.query("stu_table",newString[]{"id","sname","sage","ssex"},"id=?",newString[]{"1"},null,null,null); while(cursor.moveToNext()){ Stringname=cursor.getString(cursor.getColumnIndex("sname")); Stringage=cursor.getString(cursor.getColumnIndex("sage")); Stringsex=cursor.getString(cursor.getColumnIndex("ssex")); System.out.println("query------->"+"姓名:"+name+""+"年龄:"+age+""+"性别:"+sex); } //关闭数据库 db.close(); } } //修改数据的方法 classModifyListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可写的数据库 SQLiteDatabasedb=dbHelper.getWritableDatabase(); ContentValuescv=newContentValues(); cv.put("sage","23"); //where子句"?"是占位符号,对应后面的"1", StringwhereClause="id=?"; String[]whereArgs={String.valueOf(1)}; //参数1是要更新的表名 //参数2是一个ContentValeus对象 //参数3是where子句 db.update("stu_table",cv,whereClause,whereArgs); } } //删除数据的方法 classDeleteListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可写的数据库 SQLiteDatabasedb=dbHelper.getReadableDatabase(); StringwhereClauses="id=?"; String[]whereArgs={String.valueOf(2)}; //调用delete方法,删除数据 db.delete("stu_table",whereClauses,whereArgs); } } } StuDBHelper.java packagecom.lingdududu.testSQLiteDb; importandroid.content.Context; importandroid.database.sqlite.SQLiteDatabase; importandroid.database.sqlite.SQLiteDatabase.CursorFactory; importandroid.database.sqlite.SQLiteOpenHelper; importandroid.util.Log; publicclassStuDBHelperextendsSQLiteOpenHelper{ privatestaticfinalStringTAG="TestSQLite"; publicstaticfinalintVERSION=1; //必须要有构造函数 publicStuDBHelper(Contextcontext,Stringname,CursorFactoryfactory, intversion){ super(context,name,factory,version); } //当第一次创建数据库的时候,调用该方法 publicvoidonCreate(SQLiteDatabasedb){ Stringsql="createtablestu_table(idint,snamevarchar(20),sageint,ssexvarchar(10))"; //输出创建数据库的日志信息 Log.i(TAG,"createDatabase------------->"); //execSQL函数用于执行SQL语句 db.execSQL(sql); } //当更新数据库的时候执行该方法 publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){ //输出更新数据库的日志信息 Log.i(TAG,"updateDatabase------------->"); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Button android:id="@+id/createDatabase" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="创建数据库" /> <Button android:id="@+id/updateDatabase" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="更新数据库" /> <Button android:id="@+id/insert" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="插入数据" /> <Button android:id="@+id/update" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="更新数据" /> <Button android:id="@+id/query" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="查询数据" /> <Button android:id="@+id/delete" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="删除数据" /> </LinearLayout> 程序运行的效果图: 当点击创建数据库按钮: LogCat窗口输出的信息为: 当点击更新数据库按钮: LogCat窗口输出的信息为: 当点击查询数据库按钮: LogCat窗口输出的信息为: 使用adb命令查看数据库: 1.在命令行窗口输入adb shell回车,就进入了Linux命令行,现在就可以使用Linux的命令了。 2.ls回车,显示所有的东西,其中有个data。(ls:显示所有,cd:进入) 3.cd data回车,再ls回车,cd data回车,ls回车后就会看到很多的com.。。。,那就是系统上的应用程序包名,找到你数据库程序的包名,然后进入。 4.进去后在查看所有,会看到有databases,进入databases,显示所有就会发现你的数据库名字,这里使用的是"stu_db"。 5.sqlite3 stu_db回车就进入了你的数据库了,然后“.schema”就会看到该应用程序的所有表及建表语句。 6.之后就可以使用标准的SQL语句查看刚才生成的数据库及对数据执行增删改查了。 #sqlite3 stu_dbsqlite3 stu_dbSQLite version 3.6.22 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite>.schema.schema CREATE TABLE android_metadata (locale TEXT); CREATE TABLEstu_table(id int,sname varchar(20),sage int,ssex varchar(10));--->创建的表 sqlite>select * from stu_table; select * from stu_table; 1|xiaoming|21|male sqlite> 插入数据 sqlite>insert into stu_table values(2,'xiaohong',20,'female'); 插入的数据记得要和表中的属性一一对应 insert into stu_table values(2,'xiaohong',20,'female'); sqlite> select * from stu_table; select * from stu_table; 1|xiaoming|21|male 2|xiaohong|20|female--------------> 插入的数据sqlite> 当点击修改数据的按钮时候 sqlite> select * from stu_table; select * from stu_table; 1|xiaoming|23|male-------------->年龄被修改为232|xiaohong|20|female sqlite> 当点击删除数据的按钮 sqlite> select * from stu_table; select * from stu_table; 1|xiaoming|23|maleid=2的数据已经被删除 总之,我们可以在代码中执行数据库的增删改查,也可以在adb命令行下实现。不过因为SQLite没有客户端,不能直接的查看数据库变化后的信息,所以常用adb命令行查看数据库改变后的信息。 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/663686

优秀的个人博客,低调大师

Android开发学习笔记:浅谈Tab选项卡

Tab选项卡是一个非常方便的组件。 一.使用Tab组件的步骤: 1.在布局文件中使用FrameLayout列出Tab组件以及Tab中的内容组件 2.Activity要继承TabActivity 3.调用TabActivity的getTabHost( )方法来获得TabHost对象 4.通过TabHost创建Tab选项 二.实现不同Tab里面的内容有两种方式: 1.切换不同的Tab时候,不同Tab里面的内容在同一个Activity显示,主要是通过修改布局文件里面的id来实现的。下面是一个具体的例子: MainActivity.java packagecom.android.tab.activity; importandroid.app.TabActivity; importandroid.os.Bundle; importandroid.view.LayoutInflater; importandroid.widget.TabHost; publicclassMainActivityextendsTabActivity{ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //获得TabHost对象 TabHosttah=getTabHost(); //from(this)从TabActivity获取LayoutInflater //R.layout.main存放Tab布局 //通过TabHost获得存放Tab标签页内容的FrameLayout //是否将inflate加到根布局元素上 LayoutInflater.from(this).inflate(R.layout.main,tah.getTabContentView(),true); //设置Tab标签的内容和显示内容 tah.addTab(tah.newTabSpec("tab1").setIndicator("图片1").setContent(R.id.TextView01)); tah.addTab(tah.newTabSpec("tab2").setIndicator("图片2").setContent(R.id.TextView02)); tah.addTab(tah.newTabSpec("tab3").setIndicator("图片3").setContent(R.id.TextView03)); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/FrameLayout01" android:layout_width="wrap_content" android:layout_height="wrap_content" > <TabHost android:id="@+id/TabHost01" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/TextView01" android:background="@drawable/pic1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/TextView02" android:background="@drawable/pic2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/TextView03" android:background="@drawable/pic3" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </FrameLayout> 效果图: 1.切换不同的Tab时候,不同Tab里面的内容在不同的Activity显示 先创建三个类FirstActivity.java,SecondActivity.java,ThirdActivity.java,都是继承Activity FirstActivity.java packagecom.android.tabtest.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.widget.TextView; publicclassFirstActivityextendsActivity{ publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); TextViewtextview=newTextView(this); textview.setText("这是Tab1"); setContentView(textview); } } SecondActivity.java packagecom.android.tabtest.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.widget.TextView; publicclassSecondActivityextendsActivity{ publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); TextViewtextview=newTextView(this); textview.setText("这是Tab2"); setContentView(textview); } } ThirdActivity.java packagecom.android.tabtest.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.widget.TextView; publicclassThirdActivityextendsActivity{ publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); TextViewtextview=newTextView(this); textview.setText("这是Tab3"); setContentView(textview); } } 在layout文件夹中对main.xml进行修改 <?xmlversion="1.0"encoding="utf-8"?> <TabHostandroid:id="@android:id/tabhost"android:layout_width="fill_parent" android:layout_height="fill_parent"xmlns:android="http://schemas.android.com/apk/res/android"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp" /> </LinearLayout> </TabHost> 新建一个测试Tab的类TabDemo.java,继承于TabActivity类 packagecom.android.tabtest.activity; importandroid.app.TabActivity; importandroid.content.Intent; importandroid.content.res.Resources; importandroid.os.Bundle; importandroid.widget.TabHost; importandroid.widget.TabHost.TabSpec; publicclassTabDemoextendsTabActivity{ /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main);//这里使用了上面创建的xml文件(Tab页面的布局) Resourcesres=getResources();//ResourceobjecttogetDrawables TabHosttabHost=getTabHost();//TheactivityTabHost TabSpecspec; Intentintent;//ReusableIntentforeachtab //第一个Tab intent=newIntent(this,FirstActivity.class);//新建一个Intent用作Tab1显示的内容 spec=tabHost.newTabSpec("tab1")//新建一个Tab .setIndicator("Tab1",res.getDrawable(android.R.drawable.ic_media_play))//设置名称以及图标 .setContent(intent);//设置显示的intent,这里的参数也可以是R.id.xxx tabHost.addTab(spec);//添加进tabHost //第二个Tab intent=newIntent(this,SecondActivity.class);//第二个Intent用作Tab1显示的内容 spec=tabHost.newTabSpec("tab2")//新建一个Tab .setIndicator("Tab2",res.getDrawable(android.R.drawable.ic_menu_edit))//设置名称以及图标 .setContent(intent);//设置显示的intent,这里的参数也可以是R.id.xxx tabHost.addTab(spec);//添加进tabHost //第三个Tab intent=newIntent(this,SecondActivity.class);//第二个Intent用作Tab1显示的内容 spec=tabHost.newTabSpec("tab2")//新建一个Tab .setIndicator("Tab3",res.getDrawable(android.R.drawable.ic_menu_help))//设置名称以及图标 .setContent(intent);//设置显示的intent,这里的参数也可以是R.id.xxx tabHost.addTab(spec);//添加进tabHost tabHost.setCurrentTab(0);//设置当前的选项卡,这里为Tab1 } } 在AndroidManifest.xml里加入9~29行的声明代码 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.tabtest.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdkandroid:minSdkVersion="10"/> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".TabDemo" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activityandroid:name=".FirstActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activityandroid:name=".SecondActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest> 效果图: 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/643043

优秀的个人博客,低调大师

ceph之openstack存储解决方案学习路线

ceph分布式存储搭建经历 http://strongit.blog.51cto.com/10020534/1739488 Ceph作为OpenStack后端存储 http://linuxnote.blog.51cto.com/9876511/1789924 eph常用命令 http://linuxnote.blog.51cto.com/9876511/1788361 Ceph使用块设备完整操作流程 http://linuxnote.blog.51cto.com/9876511/1788682 本文转自heavenseahill 51CTO博客,原文链接:http://blog.51cto.com/shower/1973642,如需转载请自行联系原作者

优秀的个人博客,低调大师

Text-to-speech 入门与进阶学习笔记(android)

1,入门:让TEXT朗读起来 //1,先写一个用来检查tts是否安装的方法privatefinalstaticintCHECK_CODE=1; publicvoidcheckTts(){ IntentcheckIntent=newIntent();checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(checkIntent,CHECK_CODE);} //创建一个TTS privateTextToSpeechmTts; //这个自己先去了解下onActivityResult是怎么回事,这里不作详解 @OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){ //TODOAuto-generatedmethodstubsuper.onActivityResult(requestCode,resultCode,data); if(requestCode==CHECK_CODE){ if(resultCode==TextToSpeech.Engine.CHECK_VOICE_DATA_PASS){ //成功创建一个TTS mTts=newTextToSpeech(this,this); }else{ //否则安装一个 IntentinstallIntent=newIntent();installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);startActivity (installIntent);}}} //2,让TTS朗读起来 //onCreate方法中 //检查TTS是否正常checkTts(); //创建用组件privatespeakValue=(EditText) findViewById(R.id.speakValue); privatespeakButton=(Button) findViewById(R.id.sayHello); speakButton.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //TODOAuto-generatedmethodstub Stringtext=speakValue.getText().toString(); Log.d("result","text--&gt;"+text);sayTts(text);}}); //TTs朗读用privatevoidsayTts(Stringtext){ //最简单的例子mTts.speak(text,TextToSpeech.QUEUE_FLUSH,null); } //补充,使用TTS朗读,一定要实现OnInitListener 接口 //TTs对象创建后初始化 @OverridepublicvoidonInit(intstatus){ if(status==TextToSpeech.SUCCESS){ //设置语言区域intresult=mTts.setLanguage(Locale.US); //如果是不支持语言 if(result==TextToSpeech.LANG_MISSING_DATA||result==TextToSpeech.LANG_NOT_SUPPORTED){ Log.e("error","不支持");}}} 就这么点代码就可以正常运行了… 2,进阶使用:改变我们朗读播放的类型,回调函数的使用与自定义文字发音 1,更改播放的流类型(暂且这样说,希望,有人解释一下) //更改播放使用的流类型 //在sayTts作以下修改 //TTs朗读用privatevoidsayTts(Stringtext){HashMap<String,String>myAlarm=newHashMap(); //把播放类型,通过闹钟流实现myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,String.valueOf(AudioManager.STREAM_ALARM)); //你播放的tts在音频播放的闹钟类型流中mTts.speak(text,TextToSpeech.QUEUE_FLUSH,myAlarm); //英语原文是这样,我了解的就是以上我注释的内容 //我感觉不是很了解,希望有人帮帮 //OnAndroid,eachaudiostreamthatisplayedisassociatedwithone //streamtype,asdefinedinandroid.media.AudioManager.Foratalking //alarmclock,wewouldlikeourtexttobeplayedonthe //AudioManager.STREAM_ALARMstreamtypesothatitrespectsthealarm //settingstheuserhaschosenonthedevice. } 2,回调函数的使用 //在sayTts()中实现.. //需要实现OnUtteranceCompletedListener这个接口 //TTs朗读用 privateToasttoast;prvateContextcontext=getApplicationContext(); privatevoidsayTts(Stringtext){HashMap<String,String>myAlarm=newHashMap();mTts.setOnUtteranceCompletedListener(this); myAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"metoo"); toast=Toast.makeText(context,"metoo",Toast.LENGTH_LONG); //最简单的例子mTts.speak(text,TextToSpeech.QUEUE_FLUSH,myAlarm);} //回调函数@OverridepublicvoidonUtteranceCompleted(StringutteranceId){speakPlayBack(utteranceId);} privatevoidspeakPlayBack(Stringstr){Log.d("result","playBack-->"+str);toast.show();} 3,录制TTS朗读保存到SD卡中 //把TTS朗读结果保存 privatevoidsayTofile(Stringtext){ HashMap<String,String>ttsRender=newHashMap<String,String>(); StringdestFileName="/sdcard/tts/"+text+".wav";ttsRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,text);mTts.synthesizeToFile(text,ttsRender,destFileName); } //在 你就可以看到你刚才朗读的Text被保存了 4,自定义Text发音 //自定义文字播放 privatevoidsayTrue(Stringtext){ StringdestFileName="/sdcard/tts/"+text+".wav";mTts.addSpeech(text,destFileName); mTts.speak(text,TextToSpeech.QUEUE_FLUSH,null);} //在onclick方法中运行sayTrue(); 亲测,MP3也可以播放… 5,销毁 @OverrideprotectedvoidonDestroy(){super.onDestroy(); if(mTts!=null){ mTts.stop(); mTts.shutdown();}}

优秀的个人博客,低调大师

Android开发学习笔记:数据存取之Preference浅析

一.Preference的简介 Preference(配置)提供了一种轻量级的数据存取方法,主要应用于数据比较少的配置信息。它以“key-value”(是一个Map)对的方式将数据保存在一个XML配置文件中,例如,手机的开机问候语,可以将其以Preference方式来进行配置。也可以保存一些用户个性化设置的字体、颜色、位置等参数信息。 二.Preference存取数据的方法 使用到的接口: SharedPreferences接口和SharedPreferences.Editor接口,它们都是来自于andorid.content包。 ①SharedPreferences接口提供保存数据的方法 我们可以调用Context.getSharedPreferences(String name,int mode)方法得到SharedPreferences接口。该方法的第一个参数是文件名称,第二个参数是操作模式。操作模式有三种: MODE_PRIVATE(私有) MODE_WORLD_READABLE(可读) MODE_WORLD_WRITEABLE(可写) SharedPreferences接口的常用方法 方法名称 方法描述 edit() 返回SharedPreferences的内部接口SharedPreferences.Editor contains(String key) 判断是否包含该键值 getAll() 返回所有配置信息Map getBoolean(String key,Boolean defValue) 获得一个boolean值 getFloat(String key,float defValue) 获得一个float值 getInt(String key,int defValue) 获得一个int值 getLong(String key,long defValue) 获得一个long值 getString(String key,String defValue) 获得一个String值 ②SharedPreferences.Editor接口提供获得数据的方法 SharedPreferences.Editor接口中的getString(String key,String defValue)、getInt(String key,int defValue)等。调用SharedPreferences的edit()方法返回SharedPreferences.Editor内部接口,该接口中提供了保存数据的方法,如putString(String key,String value)、pubInt(String key,int value)等,调用该接口的commit方法可以将数据进行保存。 SharedPreferences.Editor接口常用的方法 方法名称 方法描述 clear() 清楚所有值 commit() 保存 getAll() 返回所有配置信息Map putBoolean(String key,Boolean value) 保存一个boolean值 putFloat(String key,float value) 保存一个float值 putInt(String key,int value) 保存一个int值 putLong(String key,long value) 保存一个long值 putString(String key,String value) 保存一个String值 remove(String key) 删除该键对应的键 下面是保存临时记事本内容的例子 当我们在手机上用记事本编写备忘录,日志的时候,突然要返回接电话,看短信的时候。我们就要停止编写,退出去听接电话,看短信。然而,当我们打完电话或者看完短信回来的时候,发现刚刚编写的内容还在记事本上,这就是Preference的作用了。 创建一个Activity,在其中放置一个EditText保存短信内容,放置一个Button用于发送信息。在onCreate()中通过getSharedPreferences()方法获得SharedPreferences接口,调用接口的getString()方法,获得保存内容,将内容设置到EditText中。 在onStop()方法中保存内容,使用getSharedPreferences().edit()方法获得SharedPreferences.Editor接口,调用SharedPreferences.Editor的putString()方法保存短信内容,调用commit()方法提交内容。 MainActivity.java packagecom.android.preference; importandroid.app.Activity; importandroid.content.SharedPreferences; importandroid.os.Bundle; importandroid.widget.Button; importandroid.widget.EditText; publicclassMainActivityextendsActivity{ privateEditTextmyEditText; privateButtonbtn; privatestaticfinalStringTEMP_INFO="temp_info"; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); myEditText=(EditText)findViewById(R.id.EditText1); btn=(Button)findViewById(R.id.Button1); //获得SharedPreferences实例 SharedPreferencessp=getSharedPreferences(TEMP_INFO,MODE_WORLD_READABLE); //从SharedPreferences获得备忘录的内容 Stringcontent=sp.getString("info_content",""); //在EditText中显示备忘录内容 myEditText.setText(content); } @Override protectedvoidonStop(){ super.onStop(); //获得编辑器 SharedPreferences.Editoreditor=getSharedPreferences(TEMP_INFO,MODE_WORLD_WRITEABLE).edit(); //将EditText中的文本内容添加到编辑器 editor.putString("info_content",myEditText.getText().toString()); //提交编辑器内容 editor.commit(); } } main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="备忘录" /> <EditText android:text="" android:id="@+id/EditText1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/Button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="保存" /> </LinearLayout> 效果图: 当我们退出屏幕再返回的时候,发现原来备忘录里编辑了一半的内容还在那里,其实它是把要保存的内容做诶XML文件保存在/data/data/package/shsared_prefs/下面了。 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/658521

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册