首页 文章 精选 留言 我的

精选列表

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

烂泥:haproxy学习之手机规则匹配

今天我们来介绍下有关haproxy匹配手机的一些规则配置。 一、业务需要 现在根据业务的实际需要,有以下几种不同的需求。如下: 1.1转发所有手机请求 所有通过手机端访问http.ilanni.com域名的话,全部转发到http://www.ilanni.com这个地址,而PC端不受此限制。 1.2根据url进行转发 如果手机端请求http.ilanni.com这个域名的url中,以docs或者manager这两个关键词开头的话,把该请求转发到后端的服务器,而PC端不受此限制。 也就是说手机端访问具体的url地址的话,可以正常访问。如果是直接访问http.ilanni.com域名的话,直接把该请求转发到http://www.ilanni.com这个地址。 二、haproxy配置 下面根据不同的业务需求进行配置haproxy,如下。 2.1转发所有手机请求配置 要把所有的手机端请求转到www.ilanni.com这个地址,需要我们首先把访问的终端匹配出来,haproxy可以通过hdr_sub(user-agent)这个参数把手机端匹配出来。 手机端匹配出来后,我们就可以定义相应的规则,把手机端的请求转发到www.ilanni.com这个地址了。 haproxy具体配置文件如下: global log 127.0.0.1 local0 log 127.0.0.1 local1 notice maxconn 4096 uid 188 gid 188 daemon tune.ssl.default-dh-param 2048 defaults log global mode http option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.1 option redispatch retries 3 option redispatch maxconn 2000 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 listen admin_stats bind 0.0.0.0:1080 mode http option httplog maxconn 10 stats refresh 30s stats uri /stats stats auth admin:admin stats hide-version frontend weblb bind *:80 acl is_http hdr_beg(host) http.ilanni.com acl ua hdr_sub(user-agent) -i android iphone redirect prefix http://www.ilanni.com if ua use_backend httpserver if is_http backend httpserver balance source server web1 127.0.0.1:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3 在以上配置文件中,有以下两行需要注意: acl ua hdr_sub(user-agent) -i android iphone redirect prefix http://www.ilanni.com if ua 这两行,第一行是第一个ua规则,该规则是判断是否是手机端。 注意:在此手机端,我们只匹配了安卓手机和iphone。 第二行是跳转规则,如果匹配是手机端的话,那么直接跳转到http://www.ilanni.com这个地址。 如果是PC端的话,默认跳转到httpserver这个后端服务器组。 以上配置是一台服务器对外只提供一个域名访问的请求,如果有两个域名的话,就要进行如下配置: global log 127.0.0.1 local0 log 127.0.0.1 local1 notice maxconn 4096 uid 188 gid 188 daemon tune.ssl.default-dh-param 2048 defaults log global mode http option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.1 option redispatch retries 3 option redispatch maxconn 2000 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 listen admin_stats bind 0.0.0.0:1080 mode http option httplog maxconn 10 stats refresh 30s stats uri /stats stats auth admin:admin stats hide-version frontend weblb bind *:80 acl is_http hdr_beg(host) http.ilanni.com acl is_haproxy hdr_beg(host) haproxy.ilanni.com acl ua hdr_sub(user-agent) -i android iphone redirect prefix http://www.ilanni.com if ua !is_haproxy use_backend haproxyserver if ua is_haproxy use_backend haproxyserver if is_haproxy use_backend httpserver if is_http backend httpserver balance source server web1 127.0.0.1:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3 backend haproxyserver balance source server web1 127.0.0.1:7070 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3 2.2测试转发所有手机请求 现在我们来测试该跳转功能,如下: 通过测试你会发现,在手机浏览器中输入http.ilanni.com会自动跳转到http://www.ilanni.com这个地址。 2.3根据url进行转发配置 根据手机端请求的url进行转发的话,首先也是需要匹配出手机端,然后定义url路径规则。最后结合手机端和url路径规则,进行跳转。 haproxy具体配置文件,如下: global log 127.0.0.1 local0 log 127.0.0.1 local1 notice maxconn 4096 uid 188 gid 188 daemon tune.ssl.default-dh-param 2048 defaults log global mode http option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.1 option redispatch retries 3 option redispatch maxconn 2000 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 listen admin_stats bind 0.0.0.0:1080 mode http option httplog maxconn 10 stats refresh 30s stats uri /stats stats auth admin:admin stats hide-version frontend weblb bind *:80 acl is_http hdr_beg(host) http.ilanni.com acl is_docs url_beg /docs /manager acl ua hdr_sub(user-agent) -i android iphone redirect prefix http://www.ilanni.com if ua !is_docs use_backend httpserver if ua is_docs use_backend httpserver if is_http backend httpserver balance source server web1 127.0.0.1:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3 在上述配置文件中,需要以下几行解释下。 acl is_docs url_beg /docs /manager 定义一个is_docs规则。如果url以/docs或者/manager开头的,则全部属于该规则。 acl ua hdr_sub(user-agent) -i android iphone redirect prefix http://www.ilanni.com if ua !is_docs 这两行首先是匹配出手机端,然后如果是手机端访问,并且访问的不是is_docs规则的话,则直接跳转到http://www.ilanni.com这个地址。 use_backend httpserver if ua is_docs 这条命令是,如果是手机端访问,并且访问的是is_docs规则的话,则直接跳转到httpserver这个后端服务器组。 如果是PC端的话,默认跳转到httpserver这个后端服务器组。 2.4测试根据url进行转发 根据url转发配置完毕后,我们现在来测试。如下: 通过上图,我们可以看到手机端访问http://http.ilanni.com/docs/这个连接的话,是可以直接访问的。 三、其他haproxy配置 在前面我们讲解了有关手机的相关配置,在实际的生产环境中,有时候我们会碰到一些奇奇怪怪的要求。 要求所有手机端访问的http.ilanni.com,转到指定的页面。 haproxy主要配置文件如下: frontend weblb bind *:80 acl is_http hdr_beg(host) http.ilanni.com acl ua hdr_sub(user-agent) -i android iphone redirect prefix http://www.ilanni.com/?p=10624 if ua use_backend httpserver if is_http backend httpserver balance source server web1 127.0.0.1:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3 以上配置是所有手机端访问的,都跳转到http://www.ilanni.com/?p=10624这个页面。测试如下: 通过上图,我们可以看到手机端的访问确实跳转到了我们指定的页面。 类似这样的要求,一般会在升级公司相关业务时提出,对公司的公网IP可以正常,但是外部访问时,跳转到指定的维护页面。 这个我们可以根据源IP地址进行匹配,在此就不进行详细的讲解了。 通过上图,我们可以看到手机端访问http://http.ilanni.com/manager/status这个连接的话,是可以直接访问的。 通过上图,我们可以看到如果手机端访问的不是is_docs这个规则中定义的url话,则会全部跳转到http://www.ilanni.com这个地址的。 本文转自 烂泥行天下 51CTO博客,原文链接:http://blog.51cto.com/ilanni/1710624

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

【Android进阶学习】Http编程之HttpConnection

HttpURLConnection是继承于URLConnection类,二者都是抽象类。其对象主要通过URL的openConnection方法获得的。 下面是具体的代码: packagecom.llingdududu.url; importjava.io.BufferedReader; importjava.io.InputStreamReader; importjava.net.HttpURLConnection; importjava.net.URL; importandroid.app.Activity; importandroid.os.Bundle; publicclassURLConnectionActivityextendsActivity{ StringurlStr="http://developer.android.com/"; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); try{ //实例化URL URLurl=newURL(urlStr); //使用HttpURLConnection打开连接 HttpURLConnectionhttpConnection=(HttpURLConnection)url.openConnection(); //得到输入流对象 InputStreamReaderin=newInputStreamReader(httpConnection.getInputStream()); BufferedReaderbufReader=newBufferedReader(in); StringlineStr=""; StringresultStr=""; while((lineStr=bufReader.readLine())!=null){ resultStr+=lineStr+"\n"; } System.out.println(resultStr); //关闭输入流 in.close(); //关闭连接 httpConnection.disconnect(); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } } 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/803159

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

新浪微博布局学习——妙用TabHost

正文 一、效果图 红色部分是本文要实现的目标。 二、实现 maintabs.xml <? xmlversion="1.0"encoding="UTF-8" ?> < TabHost android: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" > < FrameLayout android:id ="@android:id/tabcontent" android:layout_width ="fill_parent" android:layout_height ="0.0dip" android:layout_weight ="1.0" /> < TabWidget android:id ="@android:id/tabs" android:visibility ="gone" android:layout_width ="fill_parent" android:layout_height ="wrap_content" android:layout_weight ="0.0" /> < RadioGroup android:gravity ="center_vertical" android:layout_gravity ="bottom" android:orientation ="horizontal" android:id ="@id/main_radio" android:background ="@drawable/maintab_toolbar_bg" android:layout_width ="fill_parent" android:layout_height ="wrap_content" > < RadioButton android:text ="@string/main_home" android:checked ="true" android:id ="@+id/radio_button0" android:layout_marginTop ="2.0dip" android:drawableTop ="@drawable/icon_1_n" style ="@style/main_tab_bottom" /> < RadioButton android:id ="@+id/radio_button1" android:layout_marginTop ="2.0dip" android:text ="@string/main_news" android:drawableTop ="@drawable/icon_2_n" style ="@style/main_tab_bottom" /> < RadioButton android:id ="@+id/radio_button2" android:layout_marginTop ="2.0dip" android:text ="@string/main_my_info" android:drawableTop ="@drawable/icon_3_n" style ="@style/main_tab_bottom" /> < RadioButton android:id ="@+id/radio_button3" android:layout_marginTop ="2.0dip" android:text ="@string/menu_search" android:drawableTop ="@drawable/icon_4_n" style ="@style/main_tab_bottom" /> < RadioButton android:id ="@+id/radio_button4" android:layout_marginTop ="2.0dip" android:text ="@string/more" android:drawableTop ="@drawable/icon_5_n" style ="@style/main_tab_bottom" /> </ RadioGroup > </ LinearLayout > </ TabHost > styles.xml < style name ="main_tab_bottom" > < item name ="android:textSize" > @dimen/bottom_tab_font_size </ item > < item name ="android:textColor" > #ffffffff </ item > < item name ="android:ellipsize" > marquee </ item > < item name ="android:gravity" > center_horizontal </ item > < item name ="android:background" > @drawable/home_btn_bg </ item > < item name ="android:paddingTop" > @dimen/bottom_tab_padding_up </ item > < item name ="android:layout_width" > fill_parent </ item > < item name ="android:layout_height" > wrap_content </ item > < item name ="android:button" > @null </ item > < item name ="android:singleLine" > true </ item > < item name ="android:drawablePadding" > @dimen/bottom_tab_padding_drawable </ item > < item name ="android:layout_weight" > 1.0 </ item > </ style > home_btn_bg.xml < selector xmlns:android ="http://schemas.android.com/apk/res/android" > < item android:state_focused ="true" android:state_enabled ="true" android:state_pressed ="false" android:drawable ="@drawable/home_btn_bg_s" /> < item android:state_enabled ="true" android:state_pressed ="true" android:drawable ="@drawable/home_btn_bg_s" /> < item android:state_enabled ="true" android:state_checked ="true" android:drawable ="@drawable/home_btn_bg_d" /> < item android:drawable ="@drawable/transparent" /> </ selector > 代码说明: 1. 需要注意的是他这里把TabWidget的Visibility设置成了gone!也就是默认难看的风格不见了:,取而代之的是5个带风格的单选按钮. 2. 注意为单选按钮设置的style,其中最重要的是为其background设置了home_btn_bg.xml,也就是自定义了选中效果。 Java文件 public class MainTabActivity extends TabActivity implements OnCheckedChangeListener{ private TabHostmHost; private IntentmMBlogIntent; private IntentmMoreIntent; private IntentmInfoIntent; private IntentmSearchIntent; private IntentmUserInfoIntent; @Override protected void onCreate(BundlesavedInstanceState){ super .onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.maintabs); // ~~~~~~~~~~~~初始化 this .mMBlogIntent = new Intent( this ,HomeListActivity. class ); this .mSearchIntent = new Intent( this ,SearchSquareActivity. class ); this .mInfoIntent = new Intent( this ,MessageGroup. class ); this .mUserInfoIntent = new Intent( this ,MyInfoActivity. class ); this .mMoreIntent = new Intent( this ,MoreItemsActivity. class ); initRadios(); setupIntent(); } /** *初始化底部按钮 */ private void initRadios(){ ((RadioButton)findViewById(R.id.radio_button0)).setOnCheckedChangeListener( this ); ((RadioButton)findViewById(R.id.radio_button1)).setOnCheckedChangeListener( this ); ((RadioButton)findViewById(R.id.radio_button2)).setOnCheckedChangeListener( this ); ((RadioButton)findViewById(R.id.radio_button3)).setOnCheckedChangeListener( this ); ((RadioButton)findViewById(R.id.radio_button4)).setOnCheckedChangeListener( this ); } /** *切换模块 */ @Override public void onCheckedChanged(CompoundButtonbuttonView, boolean isChecked){ if (isChecked){ switch (buttonView.getId()){ case R.id.radio_button0: this .mHost.setCurrentTabByTag( " mblog_tab " ); break ; case R.id.radio_button1: this .mHost.setCurrentTabByTag( " message_tab " ); break ; case R.id.radio_button2: this .mHost.setCurrentTabByTag( " userinfo_tab " ); break ; case R.id.radio_button3: this .mHost.setCurrentTabByTag( " search_tab " ); break ; case R.id.radio_button4: this .mHost.setCurrentTabByTag( " more_tab " ); break ; } } } private void setupIntent(){ this .mHost = getTabHost(); TabHostlocalTabHost = this .mHost; localTabHost.addTab(buildTabSpec( " mblog_tab " ,R.string.main_home, R.drawable.icon_1_n, this .mMBlogIntent)); localTabHost.addTab(buildTabSpec( " message_tab " ,R.string.main_news, R.drawable.icon_2_n, this .mInfoIntent)); localTabHost.addTab(buildTabSpec( " userinfo_tab " ,R.string.main_my_info, R.drawable.icon_3_n, this .mUserInfoIntent)); localTabHost.addTab(buildTabSpec( " search_tab " ,R.string.menu_search, R.drawable.icon_4_n, this .mSearchIntent)); localTabHost.addTab(buildTabSpec( " more_tab " ,R.string.more, R.drawable.icon_5_n, this .mMoreIntent)); } private TabHost.TabSpecbuildTabSpec(Stringtag, int resLabel, int resIcon, final Intentcontent){ return this .mHost .newTabSpec(tag) .setIndicator(getString(resLabel), getResources().getDrawable(resIcon)) .setContent(content); } 代码说明 1. 由于TabWidget被隐藏,所以相关的事件也会无效,这里取巧用RadioGroup与RadioButton的特性来处理切换,然后监听事件调用setCurrentTabByTag来切换Activity。 2. 注意即使TabWidget被隐藏,也要为其设置indicator,否则会保持。 三、总结 在这之前如果要做这种效果我恐怕第一时间就会想到用ActivityGroup来做,主要是因为TabHost的TabWidget非常难看,用起来也不方便。其实从源码可以看出,TabActivity也是继承自ActivityGroup,这里结合了单选按钮和TabHost,各取其长,有时间可以专门写一个这样的自定义控件:) 本文转自over140 51CTO博客,原文链接:http://blog.51cto.com/over140/582149,如需转载请自行联系原作者

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

Qt学习之路(30): Graphics View Framework

现在基本上也已经到了2D绘图部分的尾声,所谓重头戏都是在最后压轴的,现在我们就要来看看在绘图部分功能最强大的Graphics View。我们经常说KDE桌面,新版本的KDE桌面就是建立在Graphics View的基础之上,可见其强大之处。 Qt的白皮书里面这样写道:“Qt Graphics View提供了用于管理和交互大量定制的 2D 图形对象的平面以及可视化显示对象的视图 widget,并支持缩放和旋转功能。Graphics View使用 BSP(二进制空间划分)树形可非常快速地找到对象,因此即使是包含百万个对象的大型场景,也能实时图形化显示。” Graphics View是一个基于item的M-V架构的框架。 基于item意思是,它的每一个组件都是一个item。这是与QPainter的状态机不同。回忆一下,使用QPainter绘图多是采用一种面向过程的描述方式,首先使用drawLine()画一条直线,然后使用drawPolygon()画一个多边形;而对于Graphics View来说,相同的过程可以是,首先创建一个场景scene,然后创建一个line对象和一个polygon对象,再使用scene的add()函数将line和polygon添加到scene,最后通过视口view就可以看到了。乍看起来,后者似乎更加复杂,但是,如果你的图像中包含了成千上万的直线、多边形之类,管理这些对象要比管理QPainter的draw语句容易得多。并且,这些图形对象也更加符合面向对象的设计要求:一个很复杂的图形可以很方便的复用。 M-V架构的意思是,Graphics View提供一个model和一个view。所谓model就是我们添加的种种对象,所谓view就是我们观察这些对象的视口。同一个model可以由很多view从不同的角度进行观察,这是很常见的需求。使用QPainter就很难实现这一点,这需要很复杂的计算,而Qt的Graphics View就可以很容易的实现。 Graphics View提供了一个QGraphicsScene作为场景,即是我们添加图形的空间,相当于整个世界;一个QGraphicsView作为视口,也就是我们观察的窗口,相当于照相机的取景框,这个取景框可以覆盖整个场景,也可以是场景的一部分;一些QGraphicsItem作为图形元件,以便scene添加,Qt内置了很多图形,比如line、polygon等,都是继承自QGraphicsItem。 下面我们来看一下代码: #include <QtGui> classDrawApp : publicQWidget { public: DrawApp(); protected: voidpaintEvent(QPaintEvent * event); }; DrawApp::DrawApp() { } voidDrawApp::paintEvent(QPaintEvent * event) { QPainter painter( this); painter.drawLine(10, 10, 150, 300); } intmain( intargc, char*argv[]) { QApplication a(argc, argv); QGraphicsScene *scene = newQGraphicsScene; scene->addLine(10, 10, 150, 300); QGraphicsView *view = newQGraphicsView(scene); view->resize(500, 500); view->setWindowTitle( "Graphics View"); view->show(); DrawApp *da = newDrawApp; da->resize(500, 500); da->setWindowTitle( "QWidget"); da->show(); returna.exec(); } 为了突出重点,我们就直接include了QtGui,不过在实际应用中不建议这么做。这里提供了直线的两种实现:一个是DrawApp使用我们前面介绍的技术,重写paintEvent()函数,这里就不在赘述,重点来看main()函数里面的实现。 首先,我们创建了一个QGraphicsScene作为场景,然后在scene中添加了一个直线,这样就把我们需要的图形元件放到了scene中。然后创建一个QGraphicsView对象进行观察。就这样,我们就是用Graphics View搭建了一个最简单的应用。运行这个程序来看结果: 第一张图是Graphics View的,第二个是DrawApp的。虽然这两个直线是同样的坐标,但是,DrawApp按照原始坐标绘制出了直线,而Graphics View则按照坐标绘制出直线之后,自动将直线居中显示在view视口。你可以通过拖动Graphics View来看直线是一直居中显示的。 这里仅仅是一个很简单的对比,不过你已经可以看到Graphics View功能的强大。仅这一个居中的操作,如果你是用QPainter,就需要很大的计算量了!当然,如果你不需要这种居中,Graphics View也是可以像QPainter绘制的一样进行显示的。 本文转自 FinderCheng 51CTO博客,原文链接:http://blog.51cto.com/devbean/241186

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

Storm概念学习系列之事务

事务 这里的事务是专门针对Topology提出来的,是为了解决元组在处理失败重新发送后的一系列问题的。简而言之,事务拓扑(transactional topology)就是指Storm以并行和顺序处理混合的方式处理元组,一方面是处理消息,将消息分为一批批,并行处理同一批内的消息以及批与批之间的消息;另一方面是提交消息,按严格的顺序提交,总之实现对消息精确的处理。 (1)事务拓扑的特点 事务性拓扑这一特性使消息在语义上确保能够以安全的方式重发消息,并保证它们只被处理一次。在不支持事务性拓扑的情况下,无法在保证准确性、可扩展性、容错性的前提下完成计算。 (2)事务拓扑的目的 事务拓扑的目的是满足对消息处理有着极其严格要求的场景,如实时计算某个用户的页面点击次数,要求结果完全精确。 (3)事务拓扑的原理 事务拓扑是Storm 0.7引入的特性,0.8之后版本已经被封装为Trident,提供了更加方便和直观的接口。 Storm的事务拓扑是完全基于底层的Spout/Bolt/Acker原语实现的,通过一层巧妙的封装得出一个优雅的实现,这也是Storm最大的魅力之一。 Storm使用ZooKeeper储存事务元数据,默认就是拓扑使用的ZooKeeper。可以通过修改transactional.zookeeper.servers和transactional.zookeeper.port配置参数键指定其他的ZooKeeper。 在使用事务性拓扑时,数据源要能够重发,有时候甚至要重复多次,因此需要确认数据源Spout是否具备这项能力。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5989741.html,如需转载请自行联系原作者

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

Android学习笔记(一) 使用选择部件

ListActivity的使用 extend Activity package com.example.listtest; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { TextView selection; ListView list; String[] items={"t0","t1","t2","t3","t4"}; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,items)); selection=(TextView)findViewById(R.id.textView1); list=(ListView)findViewById(R.id.listView1); //绑定数据 list.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,items)); list.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView< ?> arg0, View arg1, int position,long id){ selection.setText(items[position]); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } } extend ListActivity spinner的使用 package com.example.test2; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; public class MainActivity extends Activity { TextView text; Spinner sp; private String[] items={"t0","t1","t2","t3","t4"}; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text=(TextView)findViewById(R.id.textView1); sp=(Spinner)findViewById(R.id.spinner1); ArrayAdapter<String> aa=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,items); aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); sp.setAdapter(aa); sp.setOnItemSelectedListener(new OnItemSelectedListener() { public void onItemSelected(AdapterView< ?> parent, View v, int position, long id){ text.setText(items[position]); } public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub text.setText("Nothing selected!"); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } } GridView的使用 package com.example.test3; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.GridView; import android.widget.TextView; public class MainActivity extends Activity { TextView selection; GridView grid; String[] items={"t0","t1","t2","t3","t4","t5","t6","7t","t8","t9","t10","t11","t12","t13","t14","t15","t16","t17","t18","t19",}; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); selection=(TextView)findViewById(R.id.textView1); grid=(GridView)findViewById(R.id.gridView1); grid.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,items)); grid.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub selection.setText(items[arg2]); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } } AutoCompleteTextView package com.example.test5; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.MenuItem; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.TextView; import android.support.v4.app.NavUtils; import android.text.Editable; import android.text.TextWatcher; public class MainActivity extends Activity implements TextWatcher{ TextView selection; AutoCompleteTextView edit; String[] items={"teacher","core","popular","wherese","compromise","teeth"}; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); selection=(TextView)findViewById(R.id.textView1); edit=(AutoCompleteTextView)findViewById(R.id.autoCompleteTextView1); edit.addTextChangedListener(this); edit.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,items)); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } public void afterTextChanged(Editable s) { // TODO Auto-generated method stub } public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub selection.setText(edit.getText()); } } 本文转自cococo点点博客园博客,原文链接:http://www.cnblogs.com/coder2012/archive/2013/05/09/3068353.html,如需转载请自行联系原作者

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

学习iOS【3】数组、词典和集合

一、数组 1.不可变数组NSArray arrayWithObjects:使用一组对象作为元素创建不可变数组,注意数组的最后一个值需要指定为nil,用来表示参数的结束,但是nil并不会存储在数组中。 objectAtIndex:获取指定索引位置的数组元素。 @[elm1,elm2….elmn]:另外一种创建数组的简便方式,不需要以nil作为结尾元素; array[index]:另外一种获取指定索引位置元素的方式。 count:数组中元素个数。 int main(int argc, const char * argv[]) { @autoreleasepool { /*不可变数组*/ //创建不可变数组 方式一 NSArray *arr=[NSArray arrayWithObjects:@"周一",@"周二",@"周三",@"周四",@"周五",@"周六",@"周日",nil]; for(int i=0;i<[arr count];i++){ NSLog(@"%@",[arr objectAtIndex:i]); } //创建不可变数组 方式二 NSArray *arr1=@[@"周一",@"周二",@"周三",@"周四",@"周五",@"周六",@"周日"]; for(int i=0;i<[arr1 count];i++){ NSLog(@"%@",arr1[i]); } } } 2.可变数组NSMutableArray NSMutableArray array方法创建空的可变数组,数组元素个数未定,可以随着需要增长; addObject:向可变数组结尾添加元素; insertObject:obj atIndex:i :将对象obj插入数组的第i个元素。 removeObjectAtIndex:i 删除数组中第i个元素。 replaceObjectAtIndex:i withObject:obj 将数组中序号为i的对象用obj替换。 使用NSLog格式化%@可以显示整个数组,它实际上会调用每个元素的description方法。 int main(int argc, const char * argv[]) { @autoreleasepool { /*可变数组*/ NSMutableArray *marr=[NSMutableArray array]; for (int i=0; i<3; i++) { marr[i]=@(i+1); } [marr addObject:@(4)]; for (int i=0; i<[marr count]; i++) { NSLog(@"%@",marr[i]); } NSLog(@"%@",marr); } } 二、词典对象(dictionary) 词典也有两种类型:不可变词典NSDictionary和可变词典NSMutableDictionary。 1.不可变词典NSDictionary NSDictionary dictionaryWithObjectsAndKeys:创建不可变词典,参数是值-键对组合(注意顺序),以nil结尾。 allKeys:返回一个数组包含词典中的所有键; count:返回词典中的记录数; objectForKey:返回key的值对象。 int main(int argc, const char * argv[]) { @autoreleasepool { /*不可变词典*/ NSDictionary *dic=[NSDictionary dictionaryWithObjectsAndKeys:@"学生",@"1",@"教师",@"2", nil]; for (NSString *key in dic) { NSLog(@"key:%@ value:%@",key,[dic objectForKey:key]); } } } 2.可变词典NSMutableDictionary NSMutableDictionary dictionary:创建一个可变词典; setObject:forKey:把键值对添加到可变词典中; removeAllObjects:删除词典中所有的记录; removeObjectForKey:删除词典中的指定键key对应的记录; int main(int argc, const char * argv[]) { @autoreleasepool { /*可变词典*/ //创建可变词典对象 NSMutableDictionary *mdic=[NSMutableDictionary dictionary]; //添加键值对 [mdic setObject:@"学生" forKey:@"1"]; mdic[@"2"]=@"教师"; //显示键值对 NSLog(@"key:1 value is:%@",[mdic objectForKey:@"1"]);//key:1 value is:学生 NSLog(@"key:2 value is:%@",mdic[@"2"]);//key:2 value is:教师 //删除 [mdic removeObjectForKey:@"1"]; NSLog(@"mdic count:%lu",[mdic count]);//mdic count:1 [mdic removeAllObjects]; NSLog(@"mdic count:%lu",[mdic count]);//mdic count:0 } } 三、集合对象(set) set是一组单值对象集合。 1.NSSet 不可变词典 setWithObjects:以一个nil为结尾的对象数组创建一个集合。 containObject:检测某个对象是否包含在集合中。 count:集合成员个数。 2.NSMutableSet 可变词典 addObject:向集合中添加对象; removeObject:从集合中删除对象; removeAllObjects:删除集合中所有对象; unionSet:求两个集合的并集; intersectSet:求两个集合的交集 3.实例 首先我们自定义分类为NSSet添加自定义方法print。 NSSet+Printing.h #import <Foundation/Foundation.h> @interface NSSet (Printing) -(void)print; @end NSSet+Printing.m #import "NSSet+Printing.h" @implementation NSSet (Printing) -(void)print{ NSLog(@"------"); for(NSNumber *item in self){ NSLog(@"%li",(long)[item integerValue]); } } @end main.m #import <Foundation/Foundation.h> #import "NSSet+Printing.h" int main(int argc, const char * argv[]) { @autoreleasepool { //创建不可变集合 NSSet *set=[NSSet setWithObjects:@"1",@"3",@"5", @"7",nil]; //创建可变集合 NSMutableSet *mset=[NSMutableSet setWithObjects:@"1",@"2",@"3",@"4",@"5", nil]; //输出 [set print]; [mset print]; //成员测试 if([set containsObject:@"7"]==YES){ NSLog(@"set contain 7"); }else{ NSLog(@"set does not contain 7"); } //添加对象 [mset addObject:@"6"]; [mset print]; //移除对象 [mset removeObject:@"6"]; //求并集 [mset unionSet:set]; [mset print]; [mset print]; //求交集 [mset intersectSet:set]; [mset print]; } } 本文转自 陈敬(Cathy) 博客园博客,原文链接: http://www.cnblogs.com/janes/p/5467317.html ,如需转载请自行联系原作者

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

6、raid、lvm、while、until 学习笔记

Raid: Level仅用于标识磁盘组合方式的不同 raid0, raid1, raid5, raid10, raid50, jbod raid0:至少需要两块磁盘,不允许任何盘出错,没有容错能力,读写性能都提升,硬盘利用率100% raid1:至少需要两块磁盘,允许一块盘出错,镜像,硬件容错能力,读性能提升,写性能下降,硬盘利用率50% raid5:至少需要三块磁盘,允许一块盘出错,校验盘分布在各盘上,读写性能都提升,硬盘利用率(n-1)/n% raid10: 至少需要四块磁盘,允许不同组内各坏一块盘,读写性能都提升,硬盘利用率50%(先做raid1,再做raid0) jbod:在逻辑上把几个物理磁盘一个接一个串联到一起,从而提供一个大的逻辑磁盘。jbod上的数据简单的从第一个磁盘开始存储, 当第一个磁盘的存储空间用完后, 再依次从后面的磁盘开始存储数据。 mdadm: 模式化的工具 -A:装配模式 -C:创建模式 -F:监控模式 管理模式 -f模拟硬盘损坏 -r移除硬盘 -a添加硬盘 -C:创建模式 -a yes自动为创建的raid设备创建设备文件; -l 级别指定Raid级别 -n #用于创建RAID设备的设备个数; -x #用于创建RAID热备磁盘的个数; -c #指定分块大小,默认为512,单位为KB -D: 显示阵列的详细信息 --detail: -S /path/to/raid_device停止指定的RAID设备 -A /path/to/raid_device DEVICES使用指定的设备装配并启动指定的RAID设备 watch -n # 'COMMAND'每隔#执行一次指定的命令;单位为秒钟 wathc -n 1 'cat /proc/mdstat'每秒钟查看一次RAID的同步状态 练习:创建一个大小为4G的RAID5; 给其添加一个空闲盘,模拟损坏等; 停止raid; mdadm -C /dev/md5 -a yes -l 5 -n 3 -x 1 /dev/sdb{1,2,3,4} mdadm -D /dev/md5 cat /proc/mdstat mke2fs -t ext4 /dev/md5 mount /dev/md5 /mnt/ ls /mnt mdadm -f /dev/md5 /dev/sdb1 mdadm -r /dev/md5 /dev/sdb1 mdadm -a /dev/md5 /dev/sdb1 umount /mnt mdadm -S /dev/md5 mdadm -A /dev/md5 /dev/sdb{1,2,3,4} bash知识点:while循环和until循环 for varName in 列表; do 循环体 done 条件测试: 执行命令: 命令成功,条件测试成功;否则为失败; 根据$?, 状态返回值; 0表示命令执行成功,非0表示命令执行失败; 表达式: [ expression ] ` expression ` test expression while 条件测试; do 循环体 done while循环:条件测试成功,则循环;失败,则退出; 如何让while循环退出:在循环体中改变测试条件中用于控制循环次数的变量的值; 练习:求100以内所有正整数的和; declare -i sum=0 declare -i i=1 while [ $i -le 100 ]; do let sum+=$i let i++ done echo $sum 练习:通过键盘提示用户输入字符,将用户输入的小写字母转换为大写,转换一次之后,再次提醒,再输再转换;但输入quit表示退出; #!/bin/bash read -p "Enter a word: " word while [[ "$word" != "quit" ]]; do echo $word | tr 'a-z' 'A-Z' read -p "Enter a word again: " word done 练习:显示如下菜单给用户 cpu) print cpu information; mem) print memory information; disk) print disk infomation; quit) quit Enter your option: 根据用户的选择输出相应信息; 每次执行后,不退出,而由用户再次指定新的选项; #!/bin/bash # cat << EOF cpu) print cpu information; mem) print memory information; disk) print disk infomation; quit) quit EOF read -p "Enter your option: " option option=`echo $option | tr 'A-Z' 'a-z'` while [[ "$option" != "quit" ]]; do if [[ "$option" == "cpu" ]]; then cat /proc/cpuinfo elif [[ "$option" == "mem" ]]; then free -m elif [[ "$option" == "disk" ]]; then df -h else echo "Wrong option..." fi read -p "Enter your option again: " option option=`echo $option | tr 'A-Z' 'a-z'` done 练习:提示用户输入一个用户名,如果存在:显示用户UID和SHELL信息;否则,则显示无此用户; 显示完成之后,提示用户再次输入;如果是quit则退出; #!/bin/bash # read -p "Enter a user name: " userName while [[ "$userName" != "quit" ]]; do if [ -z "$userName" ]; then echo "User name null." elif id $userName &> /dev/null; then grep "^$userName\>" /etc/passwd | cut -d: -f3,7 else echo "No such user." fi read -p "Enter a user name again(quit to exit): " userName done 练习:提示用户输入一个用户名,判断用户是否登录了当前系统; 如果没有登录,则停止5秒钟之后,再次判断;直到用户登录系统,显示“用户来了”,而后退出; #!/bin/bash # read -p "Enter a user name: " userName while ! id $userName &> /dev/null; do read -p "Enter a user name again: " userName done while ! who | grep "^$userName" &> /dev/null; do echo "$userName is not here." sleep 5 done echo "$userName is on." #!/bin/bash # read -p "Enter a user name: " userName until [ -n "$userName" ] && id $userName &> /dev/null; do read -p "Enter a user name again: " userName done until who | grep "^$userName" &> /dev/null; do echo "$userName is not here." sleep 5 done echo "$userName is on." bash编程之until循环: until 测试条件; do 循环体 done 条件不满足,则循环;否则,退出; 练习:用until循环,求100以内所有正整数之和; #!/bin/bash declare -i sum=0 declare -i i=1 until [ $i -gt 100 ]; do let sum+=$i let i++ done echo $sum bash编程之组合测试条件深入探讨: 逻辑与:多个条件同时满足 [ CONDITION1 ] && [ CONDITION2 ] [ CONDITION1 -a CONDITION2 ] [[ CONDITION1 && CONDITION2 ]] 注意:前两个使用单或双中括号都可,但,&&不允许用于单中括号中,所以第三种只能用于双中括号中; 逻辑或:多个条件中有一个满足即为真; [ CONDITION1 ] || [ CONDITION2 ] [ CONDITION1 -o CONDITION2 ] [[ CONDITION1 || CONDITION2 ]] 注意:||不允许用于单中括号中; 德 摩根 定律 !(条件1 或 条件2) = !条件1 并且 !条件2 !(条件1 并且 条件2) = !条件1 或 !条件2 使用while循环一次读取文件的一行,直到文件尾部: while read line; do 循环体 done < /path/to/somefile 练习:取出当前系统上,默认shell为bash的用户 #!/bin/bash # while read line; do [[ `echo $line | cut -d: -f7` == "/bin/bash" ]] && echo $line | cut -d: -f1 done < /etc/passwd 练习:显示所有其ID号为偶数的用户; #!/bin/bash # while read line; do userID=`echo $line | cut -d: -f3` if [ $[$userID%2] -eq 0 ]; then echo -n "$userID: " echo $line | cut -d: -f1 fi done < /etc/passwd 练习:显示/etc/rc.d/rc.sysinit文件中,其总字符个数大于30的行; #!/bin/bash # while read line; do charCounts=`echo $line | wc -c` if [ $charCounts -gt 30 ]; then echo -n "$charCounts: " echo $line fi done < /etc/rc.d/rc.sysinit 练习:显示所有其UID和GID均为偶数的用户; #!/bin/bash # while read line; do userID=`echo $line | cut -d: -f3` groupID=`echo $line | cut -d: -f4` if [ $[$userID%2] -eq 0 ] && [ $[$groupID%2] -eq 0 ]; then echo -n "$userID, $groupID: " echo $line | cut -d: -f1 fi done < /etc/passwd 练习:显示/etc/rc.d/rc.sysinit文件中,其总字符个数大于30且非以“#”开头的行; #!/bin/bash # while read line; do charCounts=`echo $line | wc -c` if [ $charCounts -gt 30 ] && [[ "$line" =~ ^[^#] ]] ; then echo -n "$charCounts: " echo $line fi done < /etc/rc.d/rc.sysinit 练习:写一个脚本,完成如下任务 1、提示用户输入一个磁盘设备文件路径; 如果用户给定的路径文件不存在或不是一个块设备文件,则提示用户重新输入,直到输入正确为止,或者输入quit以9为退出码结束脚本; 2、提示用户“下面的操作会清空磁盘中的数据,并提问是否继续” 如果用户给出字符y或单词yes,则继续,否则,则提供以8为退出码结束脚本; 3、将用户指定的磁盘上的分区清空,而后创建两个主分,大小分别为100M和512M; 4、格式化此两个分区; 5、将第一个分区挂载至/mnt/boot目录;第二个分区挂载至/mnt/sysroot目录; #!/bin/bash echo -n -e "\033[31mEnter a disk path: \033[0m" read diskPath while [ $diskPath != "quit" ];do if ! [ -b $diskPath ];then echo -n -e "\033[31mEnter a disk path again: \033[0m" read diskPath else echo -n -e "\033[31mFlow action clear disk data y | n:\033[0m" read option if [[ $option == "n" ]];then exit 8 elif [[ $option == "y" ]];then dd if=/dev/zero of=$diskPath bs=512 count=1 &> /dev/null echo "n p 1 +100M n p 2 +512M w" | fdisk $diskPath &> /dev/null if mount | grep /mnt/boot &> /dev/null;then umount /mnt/boot fi if mount | grep /mnt/sysroot &> /dev/null;then umount /mnt/sysroot fi mke2fs -t ext4 ${diskPath}1 &> /dev/null mke2fs -t ext4 ${diskPath}2 &> /dev/null if ! [ -e /mnt/boot ];then mkdir /mnt/boot fi if ! [ -e /mnt/sysroot ];then mkdir /mnt/sysroot fi mount ${diskPath}1 /mnt/boot mount ${diskPath}2 /mnt/sysroot echo -e "\033[32mFinished !\033[0m" exit 0 else echo "Unkown option!" fi fi done exit 9 LVM: Logical Volume Manager 设备文件:/dev/卷组名/逻辑卷名 /dev/mapper/卷组名-逻辑卷名 物理卷管理命令:pv pvcreate创建 pvremove移除 pvscan, pvs, pvdisplay查看 pvmove 迁移 卷组的管理命令:vg vgcreate创建 vgremove移除 vgscan, vgs, vgdisplay查看 vgextend, vgreduce扩展、缩减 vgcreate, -s: PE大小, 默认4M #vgcreate -s 4M vg_name 逻辑卷的管理命令:lv lvcreate创建 lvremove移除 lvscan, lvdisplay, lvs 查看 lvextend, lvreduce 扩展、缩减 lvcreate -L :空间大小 -n : lv名称 # lvcreate -L Size -n Name vg_name 扩展卷组: 1、准备要添加的物理卷; 2、扩展卷组: 添加物理卷至卷组中; # vgextend vg_name /path/to/pv_device 缩减卷组: 1、确定要移除的物理卷的总空间大小,要小于VG当前的可用空间大小; 2、将要移除的物理卷上的所有PE移动至其它PV # pvmove /path/to/pv_device 3、缩减vg # vgreduce vg_name /path/to/pv_device 逻辑卷扩展的步骤: 1、先确定扩展的大小;并确保所属的卷组有足够的剩余空间; 2、扩展物理边界: # lvextend -L [+]Size /path/to/lv_device 3、扩展逻辑边界: # resize2fs /path/to/lv_device 缩减逻辑卷的步骤: 1、卸载卷,并执行强制检测 # e2fsck -f /path/to/lv_device 2、缩减逻辑边界: # resize2fs /path/to/lv_device SIZE 3、缩减物理边界: # lvreduce -L [-]Size /path/to/lv_device 快照卷:逻辑卷的一种,通常为只读(通常用于数据备份) # lvcreate -s -L Size -n Name -p r /path/to/original_lv_device 练习: 1、创建一个由两个物理卷组成大小为20G的卷组myvg,要求PE大小16M;而后新建 大小为7G逻辑卷mylv1,要求其文件系统为ext4,块大小为2048,且开机能自动挂载至/users; 2、新建用户openstack,其家目录为/users/openstack,而后切换至openstack用户,复制一些文件至其家目录中; 3、缩减mylv1至5G大小;而后切换至openstack用户,确保其数据没有丢失; 4、对mylv1创建快照卷snap-mylv1,并通过其备份数据至/tmp/user.tar.bz2; pvcreate /dev/sdb{1,2} vgcreate -s 16M myvg /dev/sdb{1,2} lvcreate -L 7G -n mylv1 myvg mke2fs -t ext4 -b 2048 /dev/myvg/mylv1 mkdir /users blkid /dev/myvg/mylv1 echo UUID=c457275b-5aa6-42d7-b770-5d40f44a17f4 /users ext4 defaults 0 0 >> /etc/fstab mount -a useradd -d /users/openstack openstack su - openstack cp /etc/fstab ./ umount /users e2fsck -f /dev/myvg/mylv1 resize2fs /dev/myvg/mylv1 5G lvreduce -L 5G /dev/myvg/mylv1 mount -a su - openstack cat fstab lvcreate -s -p r -L 1M -n snap-mylv1 /dev/myvg/mylv1 mount /dev/myvg/snap-mylv1 /mnt tar jcf /tmp/user.tar.bz2 /mnt umount /mnt lvremove /dev/myvg/snap-mylv1 本文转自开源殿堂 51CTO博客,原文链接:http://blog.51cto.com/kaiyuandiantang/1942533,如需转载请自行联系原作者

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

学习OpenStack之 (0):基础知识

vi 方向键出现字母问题解决方法 执行命令 sudo apt-get remove vim-common 执行命令 sudo apt-get install vim 鼠标被virtualbox捕获无法释放 按右Control键可以释放鼠标 使服务在机器重启后自启动 sudo update-rc.d ssh defaults IP段表示方法 原来“/”后面的数字其实代表了掩码。正常情况下,掩码中的“1”是不可间断的,这样只要知道掩码中“1”的个数,就可以唯一地确定一个掩码。比如“/24”就表示掩码中有24个“1”,即“11111111 11111111 11111111 00000000”,用十进点分法表示就是“255.255.255.0”。 192.168.2.12与192.168.2.20 换成2进制 192.168.2.12二进制11000000.10101000.00000010.00001100 192.168.2.20二进制11000000.10101000.00000010.00010100 相与,有27位地址相同,所以可以写成192.168.2.12/27 主机位就是2的5次方,192168.2.12/27 有32个主机位 tar命令 tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个。下面的参数是根据需要在压缩或解压档案时可选的。 -z:有gzip属性的 -j:有bz2属性的 -Z:有compress属性的 -v:显示所有过程 -O:将文件解开到标准输出 下面的参数-f是必须的 -f: 使用档案名字,切记,这个参数是最后一个参数,后面只能接档案名。 # tar -cf all.tar *.jpg 这条命令是将所有.jpg的文件打成一个名为all.tar的包。-c是表示产生新的包,-f指定包的文件名。 # tar -rf all.tar *.gif 这条命令是将所有.gif的文件增加到all.tar的包里面去。-r是表示增加文件的意思。 # tar -uf all.tar logo.gif 这条命令是更新原来tar包all.tar中logo.gif文件,-u是表示更新文件的意思。 # tar -tf all.tar 这条命令是列出all.tar包中所有文件,-t是列出文件的意思 # tar -xf all.tar 这条命令是解出all.tar包中所有文件,-x是解开的意思 压缩 tar –cvf jpg.tar *.jpg //将目录里所有jpg文件打包成tar.jpg tar –czf jpg.tar.gz *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用gzip压缩,生成一个gzip压缩过的包,命名为jpg.tar.gz tar –cjf jpg.tar.bz2 *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用bzip2压缩,生成一个bzip2压缩过的包,命名为jpg.tar.bz2 tar –cZf jpg.tar.Z *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用compress压缩,生成一个umcompress压缩过的包,命名为jpg.tar.Z rar a jpg.rar *.jpg //rar格式的压缩,需要先下载rar for linux zip jpg.zip *.jpg //zip格式的压缩,需要先下载zip for linux 解压 tar –xvf file.tar //解压 tar包 tar -xzvf file.tar.gz //解压tar.gz tar -xjvf file.tar.bz2 //解压 tar.bz2 tar –xZvf file.tar.Z //解压tar.Z unrar e file.rar //解压rar unzip file.zip //解压zip 总结 1、*.tar 用 tar –xvf 解压 2、*.gz 用 gzip -d或者gunzip 解压 3、*.tar.gz和*.tgz 用 tar –xzf 解压 4、*.bz2 用 bzip2 -d或者用bunzip2 解压 5、*.tar.bz2用tar –xjf 解压 6、*.Z 用 uncompress 解压 7、*.tar.Z 用tar –xZf 解压 8、*.rar 用 unrar e解压 9、*.zip 用 unzip 解压 指定ubuntu的源,参考http://chenrongya.blog.163.com/blog/static/8747419620143185103297/ 配置静态ip地址 $sudo vi /etc/network/interfaces 原有内容只有如下两行: auto lo iface lo inet loopback 向末尾追加以下内容: auto eth0 iface eth0 inet static address 192.168.0.33 gateway 192.168.0.1 netmask 255.255.255.0 network 192.168.0.0 broadcast 192.168.0.255 然后保存退出; 修改机器名: 修改/etc/hostname 和 /etc/hosts,再重启机器 W: GPG error: http://ppa.launchpad.net lucid Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY A1715D88E1DF1F24 Google 之,在这篇文档里有提到解决方案: http://muzso.hu/2007/05/25/how-to-fix-no_pubkey-errors-in-apt-get-update-operations 具体的解决方法步骤是(注意下面的KEY 是根据每次报错而不同的,可能需要用实际报错的KEY替换命令中的KEY值): $ sudo gpg --keyserver keyserver.ubuntu.com --recv A1715D88E1DF1F24 $sudo gpg --export --armor A1715D88E1DF1F24 | sudo apt-key add - 注:上面第二个命令中的第二个sudo,因为sudo不能跨越Pipe,所以第二个命令也需要使用sudo 在ubuntu上安装ssh server 现象: ssh client无法连到ubuntu sammydeair:~ Sammy$ ssh -l s1 10.211.55.4 ssh: connect to host 10.211.55.4 port 22: Connection refused 查看: ubuntu上ssh local,同样错误,发现是openssh-server没安装 解决: $ sudo apt-getupdate //视网络情况会花比较长的时间 $ sudo apt-getupgrade $ sudo apt-get install openssh-server $sudo /etc/init.d/ssh start 在Mac上使用过要license的Parallels Desktop和免费的VirtualBox,比较结果如下: 1. VirtualBox对鼠标的捕获和控制更加友好,Parallels需要按键来释放鼠标,但是VirtualBox里面完全自动。 2. VirtualBox里面虚拟机的运行速度似乎更快,至少关机比Parallels快。 3.VirutalBox里面可以很方便地复制虚拟机,但是在Parallels Desktop里面不知道什么原因“克隆”菜单为灰色不可用。 4. VirtualBox里面多网卡配置更方便。 5. google查到的VirtualBox的文章比Parallels Desktop多得多 至少在我看来,免费的VirtualBox要比收费的Parallels要好些。接下里继续体会VirtualBox。 在Ubuntu里面配置静态IP使得可以连接外网 1. 关闭虚机,在VirtualBox里面,设置虚机的一个网卡为桥接模式 2. 查看主机的DNS server 3. 开虚机,运行ifconfig和route命令,查看该网卡自动获得的IP,netmask,gateway s1@compute1:~$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0 10.0.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 4. 运行命令vi /etc/network/interfaces,设置静态IP,gateway,broadcast,netmask auto eth0 iface eth0 inet static address 192.168.1.15 netmask 255.255.255.0 gateway 192.168.1.1 5.配置DNS, 运行vi /etc/resolvconf/resolv.conf.d/tail, 从而在/etc/resolvconf/resolv.conf.d/目录下创建tail文件,写入 nameserver 192.168.1.1 然后重启,DNS生效 6.测试。ping www.sohu.com s1@compute1:~$ ping www.sohu.com PING fsh.a.sohu.com (114.80.130.88) 56(84) bytes of data. 64 bytes from www.sohu.com (114.80.130.88): icmp_seq=1 ttl=56 time=4.65 ms 64 bytes from www.sohu.com (114.80.130.88): icmp_seq=2 ttl=56 time=6.91 ms 64 bytes from www.sohu.com (114.80.130.88): icmp_seq=3 ttl=56 time=5.39 ms VirtualBox 虚拟机的几种网络连接方式 (1)NAT(网络地址转换模式):能从虚拟机访问外网,主机不能访问虚拟机。 网络地址转换( NAT )是最简单的方法从一个虚拟机访问外部网。通常,它并不要求在主机网络和客户机上做任何配置。基于这个原因,它是默认的网络模式 。 原理:客户机(即虚拟机)送出的网络帧被 VirtualBox 的 NAT 引擎收到,抽取 TCP/IP 数据,再通过主机的操作系统(即安装 VirtualBox 的操作系统)重新发送出去。送到在主机上的一个应用程序,或者到位于主机同一网络的另一台计算机上,它看起来好象是安装在主机上的程序 VirtualBox,通过一个属于主机的 IP 地址,把数据发送出去。VirtualBox 倾听到数据包裹的回复,通过客户机的私人网络重新包装和发送往客户机上。 效果:使用NAT模式,就是让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网。但纯NAT模式下,宿主机不能访问虚拟机。 使用场景:如果你想利用安装一个新的虚拟系统,在虚拟系统中不用进行任何手工配置就能直接访问互联网,建议你采用NAT模式. (2)Bridged方式:虚拟机和主机拥有同样的网络功能,能互相访问。 用这种方式,虚拟系统的IP可设置成和本机系统在同一网段,虚拟系统相当于网络内的一台独立的机器,和本机一起插在一个Hub上,网络内其他机器可访问虚拟系统,虚拟系统也可访问网络内其他机器,当然和本机系统的双向访问也不成问题。 (3)内部网络:虚拟机之间可以互相访问,虚拟机不能访问外网,主机和虚机之间不能访问。 内网模式,顾名思义就是内部网络模式: 虚拟机与外网完全断开,只实现虚拟机于虚拟机之间的内部网络模式。 (1)虚拟机与主机的关系:不能相互访问,彼此不属于同一个网络,无法相互访问。 (2)虚拟机与网络中其他主机的关系:不能相互访问,理由同上。 (3)虚拟机与虚拟机的关系:可以相互访问,前提是在设置网络时,两台虚拟机设置同一网络名称。 (4)host-only方式 (主机模式):虚拟机不能访问外网,主机可以访问虚拟机。 Virtualbox在宿主机中模拟出一张专供虚拟机使用的网卡,所有虚拟机都是连接到该网卡上的,虚拟机可以通过该网卡IP访问宿主机,同时Virtualbox提供一个DHCP服务,虚拟机可以获得一个内部网IP,宿主机可以通过该IP访问虚拟机。如果单纯使用Host-only模式,则虚拟机不能连接外部公共网络。 (5)通用驱动 作用和效果:运行用于选择网卡驱动。该驱动是virtualbox内部自带的,或者是通过extensionpack添加进来的。此模式实际上很少用到 一般来说,Bridged方式最方便好用。但如果本机系统是win2000而网线没插(或根本没有网卡),网络非常可能不可用(大部分用PCI网卡的机器都如此),此时就只能用NAT方式或host-only,之前所说的那两块虚拟网卡就是适应这两种网络准备的。 使用NAT和host-only混合模式,使得虚拟机既能访问外网,主机也能访问虚机 在虚机关机状态下配置网络,网卡1使用NAT模式,网卡2使用host-only模式。 1. 检查宿主机上host-only adapter的网络设置 当添加多个网卡时,比如 eth0 是 NAT 模式用于虚机访问外网,eth1 是 host-only 模式用于宿主机访问虚机,eth2 是internal 模式用于虚机之间互访,需要注意 default gateway。设置不对的话,虚机是不能访问外网的。当专有 eth0 时候,default gw 是它自己,当增加 eth1 和 eth2 后,default gw 就跑到了 eth2上,而 eth2 是不能用于外网访问的。因此,此时需要手工修改 default gw,修改为: route del default gw 192.168.1.1 route add default gw 10.0.2.2 eth0 root@ceph1:~# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 eth0 10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2 192.168.56.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 root@ceph1:~# ping www.sohu.com PING fhk.a.sohu.com (175.100.207.201) 56(84) bytes of data. 64 bytes from 175.100.207.201: icmp_seq=1 ttl=41 time=133 ms 64 bytes from 175.100.207.201: icmp_seq=2 ttl=41 time=69.9 ms 64 bytes from 175.100.207.201: icmp_seq=3 ttl=41 time=69.4 ms 64 bytes from 175.100.207.201: icmp_seq=4 ttl=41 time=68.5 ms 64 bytes from 175.100.207.201: icmp_seq=5 ttl=41 time=71.9 ms 注意 eth0 的 default gw 是 10.0.2.2 而不是 10.0.2.1. 2. 开启虚拟机配置网络 sudo vi /etc/network/interfaces sudo /etc/init.d/networking restart 可运行ifconfig查看ip 3. 可以从主机ping和ssh虚拟机了 本文转自SammyLiu博客园博客,原文链接:http://www.cnblogs.com/sammyliu/p/4139246.html,如需转载请自行联系原作者

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

android学习之-简单对话框

主类 packagesucre.android; importandroid.app.Activity; importandroid.app.AlertDialog; importandroid.content.DialogInterface; importandroid.os.Bundle; importandroid.view.View; importandroid.widget.Button; /** *创建一个简单的对话框 *@authorqiaolei * */ publicclassEX03_12extendsActivity{ privateButtonbt; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); bt=(Button)findViewById(R.id.mButton); bt.setOnClickListener(newButton.OnClickListener(){ publicvoidonClick(Viewv){ //创建一个对话框 newAlertDialog.Builder(EX03_12.this) //设置标题 .setTitle(R.string.app_about) //设置对话内容 .setMessage(R.string.app_about_msg) //设置按钮 .setPositiveButton(R.string.str_ok,newDialogInterface.OnClickListener(){ publicvoidonClick(DialogInterfacedialog,intwhich){ //点击确定后要执行的一些内容,这里选择直接结束 finish(); } }).show(); } }); } } 本文转自sucre03 51CTO博客,原文链接:http://blog.51cto.com/sucre/743340,如需转载请自行联系原作者

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

openstack学习笔记:Kvm基础实验环境

系统:centos7.1 安装环境:桌面环境、kvm基础服务 一、关闭selinux 1 2 [root@localhost~] #setenforce0 [root@localhost~] #sed-i's/enforcing/disabled/g'/etc/selinux/config 二、关闭iptables 1 2 [root@localhost~] #systemctlstopfirewalld [root@localhost~] #systemctldisablefirewalld 三、确认服务器cpu是否支持虚拟化 1 2 3 4 5 6 7 8 9 [root@localhost~] #grep-o'vmx\|svm'/proc/cpuinf vmx vmx vmx vmx vmx vmx vmx vmx 四、安装桌面 1、已经安装的软件以及可以安装的软件 2、安装图形桌面 1 [root@localhost~] #yum-ygroupinstall"XWindowSystem""GNOMEDesktop" 3、安装vncserver 1 [root@localhost~] #yum-yinstalltigervnc-server 4、配置vnc 1 2 3 4 5 6 7 8 9 10 [root@localhost~] #vncserver Youwillrequireapasswordtoaccessyourdesktops. Password: Verify: xauth: file /root/ .Xauthoritydoesnotexist New 'localhost.localdomain:1(root)' desktopislocalhost.localdomain:1 Creatingdefaultstartupscript /root/ .vnc /xstartup Startingapplicationsspecified in /root/ .vnc /xstartup Log file is /root/ .vnc /localhost .localdomain:1.log 5、使用vnc连接测试 五、安装kvm 1、安装kvm依赖包 1 2 3 4 [root@localhost~] #yum-yinstallqemu-kvmlibvirtvirt-installbridge-utilsvirt-manager [root@localhost~] #lsmod|grep kvmkvm_intel1480810 kvm4611261kvm_intel 2、启动libvirt服务 1 2 [root@localhost~] #systemctlstartlibvirtd [root@localhost~] #systemctlenablelibvirtd 这样就可以创建kvm虚拟机了 本文转自 wangpengtai 51CTO博客,原文链接:http://blog.51cto.com/wangpengtai/1953235,如需转载请自行联系原作者

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

OpenStack(Kilo版本)基础架构学习笔记

一、OpenStack项目简介 OpenStack是一个由NASA(美国国家航空航天局)和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。 OpenStack项目是一个开源的云计算平台,支持所有类型的云环境。项目的目标是提供实施简单、可扩展性强、标准统一的云计算管理平台。 通常作为一个基础设施即服务(IAAS)解决方案,OpenStack开源云操作系统中心控制大量的计算、存储和网络资源。通过管理员授权用户通过WEB界面提供资源管理,各个服务之间的通过API通信,各个模块之间通过消息队列通信。 图1.1. OpenStack免费云操作系统 下面表格列出了OpenStack服务列表。 表1.1. OpenStack服务列表 二、OpenStack历史版本 OpenStack的每个主版本系列以字母表顺序(A~Z)命名,以年份及当年内的排序做版本号,从第一版的Austin(2010.1)到目前最新的稳定版Kilo(2015.1),共经历了11个主版本。而版本Liberty和Mitaka正在开发中。 三、OpenStack概念架构 下面图是OpenStack官方提供的OpenStack架构图。该架构由OpenStack网络,可选的块存储和面向对象存储服务器组成的三个节点的架构组成。 图1.2. OpenStack架构图 架构示例: OpenStack Neutron网络的示例架构,至少需要下面三个节点: 1)控制节点(Controller node)运行身份认证服务,镜像服务,管理部分计算和网络服务,运行网络插件以及仪表板。它还包括一些支持服务,例如 SQL 数据库、消息队列和网络时间协议(NTP)。 2)网络节点(Network node)运行 Networking 插件和一些代理,并提供switching、routing、NAT 和 DHCP 服务。这个节点还处理外部(Internet) 租户虚拟机实例的连接。 3)计算节点(Compute node)运行hypervisor 管理程序,Compute 使用 KVM 作为默认的hypervisor。计算节点也可以运行Networking 插件和代理,它们连接租户网络到虚拟机上并提供防火墙(security groups) 服务。 四、OpenStack Networking(neutron)架构最小硬件配置。 图1.3. OpenStack Neutron架构最小硬件配置 五、OpenStack Networking(neutron)架构网络配置 图1.4. OpenStack Neutron架构网络配置 六、OpenStack Networking(neutron)架构服务部署 图1.5. OpenStack Neutron架构服务配置 备注: 1)OpenStack官方文档: http://docs.openstack.org/kilo/install-guide/install/apt/content/ 2)OpenStack历史版本: https://wiki.openstack.org/wiki/Releases 3)本博客测试的版本都是OpenStack Kilo版本。 本文转自 sfzhang 51CTO博客,原文链接:http://blog.51cto.com/sfzhang88/1688452,如需转载请自行联系原作者

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

Android开发学习笔记:圆角的Button

在res目录下的drawable-mdpi建立xml文件shape.xml,如下图所示: shape.xml <?xmlversion="1.0"encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <!--填充的颜色--> <solidandroid:color="#FFFFFF"/> <!--设置按钮的四个角为弧形--> <!--android:radius弧形的半径--> <cornersandroid:radius="5dip"/> <!--padding:Button里面的文字与Button边界的间隔--> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> </shape> main.xml 在android:background="@drawable/shape"就使用了shape.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/roundButton" android:text="圆角按钮" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shape" /> </LinearLayout> strings.xml <?xmlversion="1.0"encoding="utf-8"?> <resources> <stringname="hello">HelloWorld,RoundButtonDemoActivity!</string> <stringname="app_name">RoundButtonDemo</string> </resources> RoundButtonDemoActivity.java packagecom.android.RoundButtonDemo.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassRoundButtonDemoActivityextendsActivity{ ButtonroundButton; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); roundButton=(Button)findViewById(R.id.roundButton); //使用匿名类注册Button事件 roundButton.setOnClickListener(newOnClickListener() { publicvoidonClick(Viewv) { Toast.makeText(RoundButtonDemoActivity.this,"你点击了圆角按钮",Toast.LENGTH_LONG).show(); } }); } } 效果图: 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/630051

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

Android开发学习笔记:浅谈Content Provider

一.Content Provider的概念介绍 Content Providers是所有应用程序之间数据存储和检索的桥梁,它使得各个应用程序之间实现数据共享。是应用程序间共享数据的唯一途径。Content Provider 主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的接口。其中包括添加,删除,查询,更新等操作。 在Content Provider使用过程中,还需要借用ContentResolver对象间接来操作ContentProvider来获取数据。ContentResolver通过应用程序的getContentResolver()方法获得。一般情况下,ContentResolver是单实例的,但是可以有多个ContentResolver在不用的应用程序和不同的进程之间和ContentResolver交互。 二.Content Provider的简介 1.Content Provider的常用方法 //查询 query(Uri,String[],String,String[],String); //插入 insert(Uri,ContentValues); //更新 update(Uri,ContentValues,String,String[]); //删除 delete(Uri,String,String[]); //获得MIME数据类型 getType(Uri); 2.数据模型 Content Provider 将其存储的数据以数据表的形式提供给访问者,在数据表中每一行为一条记录,每一列为具有特定类型和意义的数据。每一条数据记录都包括一个 "_ID" 数值字段,改字段唯一标识一条数据。 _ID NUMBER NUMBER_KEY LABEL NAME TYPE 13 (425) 555 6677 425 555 6677 Kirklandoffice Bully Pulpit TYPE_WORK 44 (212) 555-1234 212 555 1234 NY apartment Alan Vain TYPE_HOME 45 (212) 555-6657 212 555 6657 Downtown office Alan Vain TYPE_MOBILE 53 201.555.4433 201 555 4433 Love Nest Rex Cars TYPE_HOME 3.URI URI,每一个Content Provider 都对外提供一个能够唯一标识自己数据集(data set)的URI, 如果一个Content Provider管理多个数据集,其将会为每个数据集分配一个独立的URI。Content Provider就是通过URI对象来共享其数据的。 URI的格式图如下: 各个部分的组成: A:标准前缀,是固定的,"content://"是用来标识数据是由Content Provider管理的 schema。 B:URI的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称 C:需要访问的数据字段名称。 D:如果URI中包含表示需要获取的记录的_ID;如何有D部分,则就返回该_ID对应的数据,否则表示返回整张表的数据 三.Content Provider实例 Anroid系统自带的Content Provider对象 获得系统联系人信息(姓名和手机号码)的例子 MainActivity.java packagecom.lingdududu.provide; importandroid.app.Activity; importandroid.os.Bundle; importandroid.provider.ContactsContract; importandroid.provider.ContactsContract.PhoneLookup; importandroid.database.Cursor; importandroid.graphics.Color; importandroid.widget.TextView; importandroid.content.ContentResolver; publicclassMainActivityextendsActivity{ publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); TextViewtv=newTextView(this); Stringstring=getQueryData(); //设置文本的颜色 tv.setTextColor(Color.BLUE); //设置TextView显示的内容 tv.setText(string); //设置文本字体的大小 tv.setTextSize(30.0f); //显示到屏幕 setContentView(tv); } publicStringgetQueryData(){ Stringstring=""; //得到ContentResolver对象 ContentResolvercr=getContentResolver(); //取得电话本中开始一项的光标 Cursorcursor=cr.query(ContactsContract.Contacts.CONTENT_URI,null, null,null,null); //向下移动光标 while(cursor.moveToNext()){ //取得联系人名字 intnameFieldColumnIndex=cursor .getColumnIndex(PhoneLookup.DISPLAY_NAME); Stringcontact=cursor.getString(nameFieldColumnIndex); //取得电话号码 StringContactId=cursor.getString(cursor .getColumnIndex(ContactsContract.Contacts._ID)); Cursorphone=cr.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"=" +ContactId,null,null); while(phone.moveToNext()){ StringPhoneNumber=phone .getString(phone .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); string+=(contact+":"+PhoneNumber+"\n"); } } cursor.close(); returnstring; } } 注意:记得在AndroidManifest.xml加上17行的权限声明 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.lingdududu.provide" 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> </application> <uses-permissionandroid:name="android.permission.READ_CONTACTS"/> </manifest> 通讯录中联系人的信息: 效果图: 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/667264

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

Android开发学习笔记:Activity的简介

1.Activity的概念介绍 Activity是Android组件中最基本也是最常用的一种组件,在一个Android应用中,一个Activity通常就是一个单独的屏幕。每一个Activity都被实现为一个独立的类,并且继承于Activity这个基类。 activity类处于android.app包中,继承体系如下: 1.java.lang.Object 2.android.content.Context 3.android.app.ApplicationContext 4.android.app.Activity 2.Activity的创建 Activity提供了和用户交互的可视化界面。创建一个Activity一般是继承Activity(也可以是LisActivity,MapActivity等),覆盖Activity的onCreate( )方法,在该方法中调用setContentView( )方法来展示要显示的视图,调用findViewById( )方法实例化组件。注意Activity只有在清单文件中声明才能使用。 3.Activity的应用实例 3.1两个Activity之间的切换 要做到两个Activity之间的切换(也就是从一个Activity启动另一个Activity),可以使用startActivity( )方法或者startActivityForResult( ) (能够返回结果)。这两个方法要传递的参数是组件Intent。 下面的实例是MainActivity和SecondActivity之间的切换: 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/hello1" /> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="转到SecondActivity" /> </LinearLayout> second.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/hello2" /> <Button android:id="@+id/secondBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="返回" /> </LinearLayout> MainActivity.java packagecom.android.test.activity; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ privateButtonbtn; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); btn=(Button)findViewById(R.id.btn); //响应按钮btn事件 btn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //显示方式声明Intent,直接启动SecondActivity Intentit=newIntent(MainActivity.this,SecondActivity.class); //启动Activity startActivity(it); } }); } } SecondActivity.java packagecom.android.test.activity; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassSecondActivityextendsActivity{ privateButtonsecondBtn; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.second); secondBtn=(Button)findViewById(R.id.secondBtn); //响应按钮secondBtn事件 secondBtn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //显示方式声明Intent,直接启动MainActivity Intentintent=newIntent(SecondActivity.this,MainActivity.class); //启动Activity startActivity(intent); } }); } } AndroidManifest.xml清单文件,16~18行为SecondActivity在清单文件里的声明 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.test.activity" 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> <activityandroid:name=".SecondActivity" android:label="@string/app_name"> </activity> </application> </manifest> 效果图: 3.2.Activity之间传递数据 在Android开发中不同的Activity之间要传递数据,就需要用到对象Bundle,讲要传递的信息封装在该对象里面,并通过Intent对象传递到另一个Intent中。 下面的实例在MainActivity中输入用户名数据,并将该用户名传递给SecondActivity: 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" /> <EditText android:id="@+id/txt" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="请输入用户名" /> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确定" /> </LinearLayout> second.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:id="@+id/secondTxt" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> strings.xml <?xmlversion="1.0"encoding="utf-8"?> <resources> <stringname="hello">MainActivity</string> <stringname="app_name">ActivityDemo</string> <stringname="app_name1">SecondActivity</string> </resources> MainActivity.java packagecom.android.test.activity; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.EditText; publicclassMainActivityextendsActivity{ privateButtonbtn; privateEditTexttxt; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); btn=(Button)findViewById(R.id.btn); txt=(EditText)findViewById(R.id.txt); //响应按钮btn事件 btn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //获得用户名字符串 StringuseName=txt.getText().toString(); //声明Bundle对象 Bundledata=newBundle(); //讲用户名信息添加到Bundle data.putString("useName",useName); //显示方式声明Intent,直接启动SecondActivity Intentit=newIntent(MainActivity.this,SecondActivity.class); //为Intent添加Bundle it.putExtras(data); //启动Activity startActivity(it); } }); } } SecondActivity.java packagecom.android.test.activity; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.widget.TextView; publicclassSecondActivityextendsActivity{ privateTextViewsecondTxt; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.second); //获得Intent Intentit=getIntent(); //从Intent中获得Bundle对象 Bundlebundle=it.getExtras(); //从Bundle中获得那么 Stringname=bundle.getString("useName"); secondTxt=(TextView)findViewById(R.id.secondTxt); secondTxt.setText(name); } } AndroidManifest.xml清单文件 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.test.activity" 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> <activityandroid:name=".SecondActivity" android:label="@string/app_name1"> </activity> </application> </manifest> 效果图: 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/636587

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

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

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

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

用户登录
用户注册