首页 文章 精选 留言 我的

精选列表

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

Android开发学习:使用已有的sql数据库

之前我们使用的数据库都是在代码里面创建的。下面介绍一下如果使用外部已有的sql数据库。 先用SQLite管理工具,sqliteadmin 具体操作很简单,在这里我就不详细介绍的了,但有一个地方时候很值得注意的,就是用sqliteadmin创建数据库的时候,数据库保存的路径不能是中文路径,中文路径会出现下面的错误提示: 我在sqliteadmin 创建好数据库StuDB,里面的表如下: 将创建好的数据库在DDMS中点击导入到data/data/程序的包名/ SQLiteTestActivity.java packagecom.lingdududu.test; importandroid.app.Activity; importandroid.database.Cursor; importandroid.database.sqlite.SQLiteDatabase; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.EditText; importandroid.widget.Toast; publicclassSQLiteTestActivityextendsActivity{ /**Calledwhentheactivityisfirstcreated.*/ privateEditTextstudentText; privateEditTextteacherText; privateButtonqueryBtn; SQLiteDatabasestuDb; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); studentText=(EditText)findViewById(R.id.stu_name); teacherText=(EditText)findViewById(R.id.teacher_name); queryBtn=(Button)findViewById(R.id.query); queryBtn.setOnClickListener(newqueryListener()); } classqueryListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ //调用查询方法 query(); stuDb.close(); } } //查询方法 privatevoidquery(){ //打开或者创建数据库 stuDb=SQLiteDatabase.openOrCreateDatabase("data/data/com.lingdududu.test/StuDB.s3db",null); try{ Stringstring=studentText.getText().toString(); Stringsql="SelectsnamefromStudentwheresnumber="+string; Cursorcursor=stuDb.rawQuery(sql,null); cursor.moveToFirst(); teacherText.setText(cursor.getString(cursor.getColumnIndex("sname"))); }catch(Exceptione){ Toast.makeText(this,"请检查输入的学生学号是否正确",Toast.LENGTH_LONG).show(); } } } 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/input_name" /> <EditText android:id="@+id/stu_name" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/query" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="开始查询" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/teacher_name" /> <EditText android:id="@+id/teacher_name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:editable="false" /> </LinearLayout> strings.xml <?xmlversion="1.0"encoding="utf-8"?> <resources> <stringname="hello">HelloWorld,SQLiteTestActivity!</string> <stringname="app_name">SQLiteTest</string> <stringname="input_name">请输入学生学号</string> <stringname="teacher_name">该学生的姓名</string> </resources> 效果图: 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/728272

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

Android开发学习笔记:Android很有用的代码片段

1:查看是否有存储卡插入 Stringstatus=Environment.getExternalStorageState(); if(status.equals(Enviroment.MEDIA_MOUNTED)){ 说明有SD卡插入 } 2:让某个Activity透明 OnCreate中不设Layout this.setTheme(R.style.Theme_Transparent); 以下是Theme_Transparent的定义(注意transparent_bg是一副透明的图片) 3:在屏幕元素中设置句柄 使用Activity.findViewById来取得屏幕上的元素的句柄.使用该句柄您可以设置或获取任何该对象外露的值. TextViewmsgTextView=(TextView)findViewById(R.id.msg); msgTextView.setText(R.string.push_me); 4:发送短信 Stringbody=”thisismmsdemo”; Intentmmsintent=newIntent(Intent.ACTION_SENDTO,Uri.fromParts(”smsto”,number,null)); mmsintent.putExtra(Messaging.KEY_ACTION_SENDTO_MESSAGE_BODY,body); mmsintent.putExtra(Messaging.KEY_ACTION_SENDTO_COMPOSE_MODE,true); mmsintent.putExtra(Messaging.KEY_ACTION_SENDTO_EXIT_ON_SENT,true); startActivity(mmsintent); 5:发送彩信 StringBuildersb=newStringBuilder(); sb.append(”file://”); sb.append(fd.getAbsoluteFile()); Intentintent=newIntent(Intent.ACTION_SENDTO,Uri.fromParts(”mmsto”,number,null)); //Belowextradatasarealloptional. intent.putExtra(Messaging.KEY_ACTION_SENDTO_MESSAGE_SUBJECT,subject); intent.putExtra(Messaging.KEY_ACTION_SENDTO_MESSAGE_BODY,body); intent.putExtra(Messaging.KEY_ACTION_SENDTO_CONTENT_URI,sb.toString()); intent.putExtra(Messaging.KEY_ACTION_SENDTO_COMPOSE_MODE,composeMode); intent.putExtra(Messaging.KEY_ACTION_SENDTO_EXIT_ON_SENT,exitOnSent); startActivity(intent); 7:发送Mail mime=“img/jpg”; shareIntent.setDataAndType(Uri.fromFile(fd),mime); shareIntent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(fd)); shareIntent.putExtra(Intent.EXTRA_SUBJECT,subject); shareIntent.putExtra(Intent.EXTRA_TEXT,body); 8:注册一个BroadcastReceiver registerReceiver(mMasterResetReciever,newIntentFilter(”oms.action.MASTERRESET”)); privateBroadcastReceivermMasterResetReciever=newBroadcastReceiver(){ publicvoidonReceive(Contextcontext,Intentintent){ Stringaction=intent.getAction(); if(”oms.action.MASTERRESET”.equals(action)){ RecoverDefaultConfig(); } } }; 9:定义ContentObserver,监听某个数据表 privateContentObservermDownloadsObserver=newDownloadsChangeObserver(Downloads.CONTENT_URI); privateclassDownloadsChangeObserverextendsContentObserver{ publicDownloadsChangeObserver(Uriuri){ super(newHandler()); } @Override publicvoidonChange(booleanselfChange){} } 10:获得手机UA publicStringgetUserAgent(){ Stringuser_agent=ProductProperties.get(ProductProperties.USER_AGENT_KEY,null); returnuser_agent; } 11:清空手机上Cookie CookieSyncManager.createInstance(getApplicationContext()); CookieManager.getInstance().removeAllCookie(); 12:建立GPRS连接 //DialtheGPRSlink. privatebooleanopenDataConnection(){ //Setupdataconnection. DataConnectionconn=DataConnection.getInstance(); if(connectMode==0){ ret=conn.openConnection(mContext,“cmwap”,“cmwap”,“cmwap”); }else{ ret=conn.openConnection(mContext,“cmnet”,“”,“”); } } 13:PreferenceActivity用法 publicclassSettingextendsPreferenceActivity{ publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.settings); } } Setting.xml: android:key=”seting2″ android:title=”@string/seting2″ android:summary=”@string/seting2″/> android:key=”seting1″ android:title=”@string/seting1″ android:summaryOff=”@string/seting1summaryOff” android:summaryOn=”@stringseting1summaryOff”/> 14:通过HttpClient从指定server获取数据 DefaultHttpClienthttpClient=newDefaultHttpClient(); HttpGetmethod=newHttpGet(“http://www.baidu.com/1.html”); HttpResponseresp; Readerreader=null; try{ //AllClientPNames.TIMEOUT HttpParamsparams=newBasicHttpParams(); params.setIntParameter(AllClientPNames.CONNECTION_TIMEOUT,10000); httpClient.setParams(params); resp=httpClient.execute(method); intstatus=resp.getStatusLine().getStatusCode(); if(status!=HttpStatus.SC_OK)returnfalse; //HttpStatus.SC_OK; returntrue; }catch(ClientProtocolExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }finally{ if(reader!=null)try{ reader.close(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } 15:显示toast Toast.makeText(this._getApplicationContext(),R.string._item,Toast.LENGTH_SHORT).show(); 16:在当前Activity中启动另外一个Activity startActivity(newIntent(this,目标Activity.class)); 17:从当前ContentView从查找控件 (Button)findViewById(R.id.btnAbout) R.id.btnAbout指控件id。 18:获取屏幕宽高 DisplayMetricsdm=newDisplayMetrics(); //获取窗口属性 getWindowManager().getDefaultDisplay().getMetrics(dm); intscreenWidth=dm.widthPixels;//320 intscreenHeight=dm.heightPixels;//480 19:无标题栏、全屏 //无标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); //全屏模式 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 注意在setContentView()之前调用,否则无效。 20注册activity 所有用到的Activity都必须在AndroidManifest.xml中注册,否则会报空指针错误。 如:,注意是包名+类名。 会持续更新...................... 本文转自 lingdududu 51CTO博客,原文链接http://blog.51cto.com/liangruijun/722171

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

Android开发学习笔记:浅谈3大类菜单

在Android系统中,菜单可以分为三类:选项菜单(Option Menu),上下文菜单(Context Menu)以及子菜单(Sub Menu)。 一.选项菜单(Option Menu) 创建选项菜单的步骤: 1.覆盖Activity的onCreateOptionMenu(Menu menu)方法,当菜单第一次被打开时调用 2.调用Menu的add( )方法添加菜单项(MenuItem),同时可以调用MenuItem的setIcon( )方法来为菜单项设置图标 3.当菜单项(MenuItem)被选择时,覆盖Activity的onOptionsItemSelected(MenuItem item)来响应事件 选项菜单的实例: packagecom.android.menu.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.view.Menu; importandroid.view.MenuItem; publicclassOptionMenuActivityextendsActivity{ //声明菜单项常量 privatestaticfinalintITEM_1=Menu.FIRST; privatestaticfinalintITEM_2=Menu.FIRST+1; privatestaticfinalintITEM_3=Menu.FIRST+2; publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); } //覆盖onCreateOptionsMenu(Menumenu)来添加菜单项 publicbooleanonCreateOptionsMenu(Menumenu){ //android.R使用的是系统自带的图标 menu.add(0,ITEM_1,0,"开始").setIcon(android.R.drawable.ic_media_play); menu.add(0,ITEM_2,0,"帮助").setIcon(android.R.drawable.ic_menu_help); menu.add(0,ITEM_3,0,"退出").setIcon(android.R.drawable.ic_menu_close_clear_cancel); returntrue; } //覆盖onOptionsItemSelected(MenuItemitem)来响应菜单选项被单击事件 publicbooleanonOptionsItemSelected(MenuItemitem){ switch(item.getItemId()){ caseITEM_1: setTitle("开始游戏!"); break; caseITEM_2: setTitle("查看帮助!"); break; caseITEM_3: setTitle("退出游戏!"); break; } returntrue; } } 效果图: 二.上下文菜单(Context Menu) 创建上下文菜单的步骤: 1.覆盖Activity的onCreateOptionMenu(Menu menu)方法,调用Menu的add( )方法添加菜单项(MenuItem). 2.覆盖Activity的onOptionsItemSelected(MenuItem item)来响应事件 3.调用registerForContextMenu( )方法来为视图注册上下文菜单 上下文菜单的实例(按住“测试Context Menu”2秒,就会出现上下文菜单): packagecom.android.context.activity; importandroid.app.Activity; importandroid.graphics.Color; importandroid.os.Bundle; importandroid.view.ContextMenu; importandroid.view.Menu; importandroid.view.MenuItem; importandroid.view.View; importandroid.view.ContextMenu.ContextMenuInfo; importandroid.widget.TextView; publicclassContextMenuActivityextendsActivity{ privatestaticfinalintITME_1=Menu.FIRST; privatestaticfinalintITME_2=Menu.FIRST+1; privatestaticfinalintITME_3=Menu.FIRST+2; privateTextViewtext; publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); text=(TextView)findViewById(R.id.TextView_1); //调用registerForContextMenu()来注册上下文菜单 registerForContextMenu(text); } @Override publicvoidonCreateContextMenu(ContextMenumenu,Viewv, ContextMenuInfomenuInfo){ menu.add(0,ITME_1,0,"红色背景"); menu.add(0,ITME_2,0,"蓝色背景"); menu.add(0,ITME_3,0,"白色背景"); } @Override publicbooleanonContextItemSelected(MenuItemitem){ switch(item.getItemId()){ caseITME_1: //设置TextView的背景颜色 text.setBackgroundColor(Color.RED); break; caseITME_2: text.setBackgroundColor(Color.BLUE); break; caseITME_3: text.setBackgroundColor(Color.WHITE); break; } returntrue; } } 效果图: 三.子菜单(Sub Menu) 创建子菜单的步骤: 1.覆盖Activity的onCreateOptionMenu(Menu menu)方法,调用Menu的addSubMenu( )方法来添加子菜单(Sub Menu) 2.调用SubMenu的add( )方法来添加子菜单(Sub Menu) 3.覆盖onContextItemSelect( )方法来响应菜单单击事件 子菜单的实例: packagecom.android.sub.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.view.Menu; importandroid.view.MenuItem; importandroid.view.SubMenu; publicclassSubMenuActivityextendsActivity{ privatestaticfinalintITEM_1=Menu.FIRST; privatestaticfinalintITEM_2=Menu.FIRST+1; publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); } //覆盖onCreateOptionsMenu(Menumenu)方法,添加子菜单项 publicbooleanonCreateOptionsMenu(Menumenu){ SubMenuad=menu.addSubMenu("添加").setIcon(android.R.drawable.ic_menu_add); SubMenure=menu.addSubMenu("关闭").setIcon(android.R.drawable.ic_menu_close_clear_cancel); ad.add(0,ITEM_1,0,"文件"); ad.add(0,ITEM_2,0,"图片"); returntrue; } //覆盖onOptionsItemSelected(MenuItemitem),响应菜单选项被单击事件 publicbooleanonOptionsItemSelected(MenuItemitem){ switch(item.getItemId()){ caseITEM_1: setTitle("添加文件!"); break; caseITEM_2: setTitle("添加图片!"); break; } returntrue; } } 效果图: 注:menu.add的方法中的参数: 1.int类型的group ID参数,代表的是组概念,你可以将几个菜单项归为一组,以便更好的以组的方式管理你的菜单按钮。可以用到的方法有: removeGroup(id) setGroupCheckable(id, checkable, exclusive) setGroupEnabled(id,boolean enabled) setGroupVisible(id,visible)2.int类型的item ID参数,代表的是项目编号。这个参数非常重要,一个item ID对应一个Menu中的选项。在后面使用菜单的时候,就是靠这个item ID来判断,你选中的是哪个选项。3.int类型的order ID参数,代表的是菜单项的显示顺序。默认是0,表示菜单的显示顺序就是按照add的顺序来显示。4.String类型的title参数,表示选项中显示的文字。 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/641275

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

Hadoop概念学习系列之Hadoop 产生背景(四)

Hadoop 最早起源于 Apache Nutch 。Nutch 是一个开源的网络搜索引擎,由 Doug Cutting 于 2002 年创建。Nutch 的设计目标是构建一个大型的全网搜索引擎,包括网页抓取、索引、 查询等功能,但随着抓取网页数量的增加,遇到了严重的可扩展性问题,即不能解决数十 亿网页的存储和索引问题。之后,谷歌发表的两篇论文为该问题提供了可行的解决方案。一篇是2003 年发表的关于谷歌分布式文件系统(GFS)的论文 。该论文描述了谷歌搜索引擎网页相关数据的存储架构,该架构可解决 Nutch 遇到的网页抓取和索引过程中产生的超大文件存储需求的问题。但由于谷歌仅开源了思想而未开源代码,Nutch 项目组便根据论文完成了一个开源实现,即 Nutch的分布式文件系统(NDFS)。另一篇是2004 年发表的关于谷歌分布式计算框架MapReduce 的论文 。该论文描述了谷歌内部最重要的分布式计算框架 MapReduce 的设计艺术,该框架可用于处理海量网页的索引问题。同样,由于谷歌未开源代码,Nutch 的开发人员完成了一个开源实现。由于 NDFS 和 MapReduce 不仅适用于搜索领域,2006 年年初,开发人员便将其移出 Nutch,成为 Lucene 的一个子项目,称为Hadoop。大约同一时间,Doug Cutting 加入雅虎公司,且公司同意组织一个专门的团队继 续发展 Hadoop。同年 2 月,Apache Hadoop 项目正式启动以支持 MapReduce 和 HDFS 的独立发展。2008 年 1 月,Hadoop 成为 Apache 顶级项目,迎来了它的快速发展期。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5058129.html,如需转载请自行联系原作者

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

Android开发学习笔记:Button事件实现方法的总结

下面介绍Button事件实现的两种方法 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/myButton1" android:text="按钮1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/myButton2" android:text="按钮2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> strings.xml <?xmlversion="1.0"encoding="utf-8"?> <resources> <stringname="hello">HelloWorld,ButtonDemoActivity!</string> <stringname="app_name">ButtonDemo</string> </resources> 第一种: ButtonDemoActivity.java packagecom.android.ButtonDemo.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassButtonDemoActivityextendsActivity{ ButtonmyButton1,myButton2; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); myButton1=(Button)findViewById(R.id.myButton1); myButton2=(Button)findViewById(R.id.myButton2); //使用匿名类注册Button事件 myButton1.setOnClickListener(newOnClickListener() { publicvoidonClick(Viewv) { Toast.makeText(ButtonDemoActivity.this,"你点击了按钮1",Toast.LENGTH_LONG).show(); } }); myButton2.setOnClickListener(newOnClickListener() { publicvoidonClick(Viewv) { Toast.makeText(ButtonDemoActivity.this,"你点击了按钮2",Toast.LENGTH_LONG).show(); } }); } } 第二种: ButtonDemoActivity.java packagecom.android.ButtonDemo.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassButtonDemoActivityextendsActivity{ ButtonmyButton1,myButton2; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); myButton1=(Button)findViewById(R.id.myButton1); myButton2=(Button)findViewById(R.id.myButton2); myButton1.setOnClickListener(newButtonClick()); myButton2.setOnClickListener(newButtonClick()); } //创建一个类,来响应OnClickListener classButtonClickimplementsOnClickListener { publicvoidonClick(Viewv) { switch(v.getId()){ caseR.id.myButton1: Toast.makeText(ButtonDemoActivity.this,"你点击了按钮1",Toast.LENGTH_LONG).show(); break; caseR.id.myButton2: Toast.makeText(ButtonDemoActivity.this,"你点击了按钮2",Toast.LENGTH_LONG).show(); break; default: break; } } } } 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/629329

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

Hadoop HDFS概念学习系列之HDFS Block(八)

块是文件系统中的一个很重要的概念。在UNIX/Linux系统中有一个数据块(DataBlock)的概念,Data Block是文件系统读写的最小数据单元。一般在文件系统中数据块的大小是512字节,一个文件所占的大小就是数据块大小的整数倍.对于用户来讲对文件的访问/存取都是透明的,同样系统管理员可以利用系统本身的命令对数据块进行相关操作。因此单从文件系统来讲,HDFS也有一个块(Block)的概念,不同之处在于HDFS为了满足大数据的效率和整个集群的吞吐量选择了更大的数值,默认为64MB。和一般的文件系统不同的是:虽然块设置得比较大,但是当一个文件的大小小于HDFS的块大小时,实际存储所占的大小并不占用一个块的大小。 客户端在读取HDFS上的一个文件时就以块为基本的数据单元。例如一次简单读取,首先,客户端把文件名和程序指定的字节偏移,根据固定的Block大小,转换成文件的Block索引。然后,客户端把文件名和Block索引发送给Master节点,Master节点将相应的Block标识和副本的位置信息返回给客户端,客户端用文件名和Block索引作为key缓存这些信息,之后客户端发送请求到其中的一个副本,一般会选择最近的。请求信息包含了Block的标识和字节范围。在对这个Block的后续读取操作中,客户端不必再和Master节点通信了,除非缓存的元数据信息过期或文件被重新打开。实际上,客户端通常会在一次请求中查询多个Block信息,Master节点的回应也可能包含了紧跟着这些被请求的Block后面的Block的信息。在实际应用中,这些额外的信息在不花费任何代价的情况下,避免了客户端和Master节点未来可能会发生的几次通信。 我们知道,在操作系统中都有一个文件块的概念,文件以块的形式存储在磁盘中,此处块的大小代表系统读/写可操作的最小文件大小。也就是说,文件系统每次只能操作磁盘块大小的整数倍数据。通常来说,一个文件系统块大小为几千字节,而磁盘块大小为512字节。文件的操作都由系统完成,这些对用户来说都是透明的。 这里,我们所要介绍的HDFS中的块是一个抽象的概念,它比上面操作系统中所说的块要大得多。在配置Hadoop系统时会看到,它的默认块大小为64MB。和单机上的文件系统相同,HDFS分布式文件系统中的文件也被分成块进行存储,它是文件存储处理的逻辑单元。 HDFS作为一个分布式文件系统,设计是用来处理大文件的,使用抽象的块会带来很多好处。一个好处是可以存储任意大的文件而又不会受到网络中任一单个节点磁盘大小的限制。可以想象一下,单个节点存储100TB的数据是不可能的,但是由于逻辑块的设计,HDFS可以将这个超大的文件分成众多块,分别存储在集群的各台机器上。另外一个好处是使用抽象块作为操作的单元可简化存储子系统。这里之所以提到简化,是因为这是所有系统的追求,而对故障出现频繁和种类繁多的分布式系统来说,简化就显得尤为重要。在HDFS中块的大小固定,这样它就简化了存储系统的管理,特别是元数据信息可以和文件块内容分开存储。不仅如此,块更有利于分布式文件系统中复制容错的实现。在HDFS中,为了处理节点故障,默认将文件块副本数设定为3份,分别存储在集群的不同节点上。当一个块损坏时,系统会通过NameNode获取元数据信息,在另外的机器上读取一个副本并进行存储,这个过程对用户来说都是透明的。当然,这里的文件块副本冗余量可以通过文件进行配置,比如在有些应用中,可能会为操作频率较高的文件块设置较高的副本数最以提高集群的吞吐量。 在HDFS中,可以通过终端命令直接获得文件和块信息,比如以下命令可以列出文件系统中组成各个文件的块。 hadoop fsck/ -files -blocks 我们知道数据块(Block) 在讨论文件系统的时候,特别是在分析文件系统的实现时,我们知道,为了便于管理,设备往往将存储空间组织成为具有一定结构的存储单位。如磁盘,文件是以块的形式存储在磁盘中,块的大小代表系统读/写操作的最小单位;在Linux的Ext3文件系统中,块大小默认为4095字节。文件系统通过一个块大小的整数倍的数据块,来使用磁盘。磁盘上的数据块管理属于文件系统实现的内部细节,对于通过系统调用读写文件的用户来说,是透明的。 HDFS也有块的概念,不过是更大的单元,默认FiDFS数据块大小是64MB。和普通文件系统类似,HDFS上的文件也进行分块,块作为单独的存储单元,以Linux上普通文件的形式保存在数据节点的文件系统中。数据块是HDFS的文件存储处理的单元。 HDFS是针对大文件设计的分布式系统,使用数据块带来了很多的好处,具体如下: 1) HDFS可以保存比存储节点单一磁盘大的文件。 文件块可以保存在不同的磁盘上。其实,在HDFS中,文件数据可以存放在集群上的任何一个磁盘上,不需要保存在同一个磁盘上。或同一个机器的不同磁盘上。 2)简化了存储子系统。 简单化是所有系统的追求,特别是在故障种类繁多的分布式系统,将管理“块”和管理“文件”的功能区分开,简化了存储管理,也消除了分布式管理文件元数据的复杂性。 3)方便容错,有利干数据复制。 在HDFS中,为了应对损坏的块以及磁盘、机器故障,数据块会在不同的机器上进行复制(一般副本数为3,即一份数据保存在3个不同的地方),如果一个数据块副本丢失或者损坏了,系统会在其他地方读取副本,这个过程对用户来说是透明的,它实现了分布式系统中的位置透明性和故障透明性。同时,一个因损坏或机器故障而丢失的块会从其他地方复制到某一个正常运行的机器,以保证副本数目恢复到正常水平。该正常水平的副本数,也称副本系数。 HDFS的数据块比前面讨论过的磁盘块大得多,一个典型HDFS系统中,磁盘块的大小为64MB,也有使用128MB和256MB数据块大小的集群。为什么在HDFS中要使用这么大的数据块呢?原因和在磁盘上使用大磁盘块的原理是一样的。在普通文件系统中使用较大的磁盘块,可以减少管理数据块需要的开销,如在Linux中可以减少保存在i-node中磁盘地址表中的信息链的长度:同时,在对文件进行读写时,可以减少寻址开销,即磁盘定位数据块的次数。HDFS中使用大数据块,可以减少名字节点上管理文件和数据块关系的开销,同时,对数据块进行读写时,可以有效地减少建立网络连接需要的成本。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5081487.html,如需转载请自行联系原作者

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

Hadoop MapReduce概念学习系列之MapReduce模型(十二)

在并行计算领域最著名的就是MPI模型,MPI是一种消息传递编程模型,在大规模科学计算领域已经成功应用了数年,而MapReduce则是一种近几年出现的相对较新的并行编程技术,但是MapReduce计算模型也是建立在数学和计算机科学基础上的,实践已经证明这种并行编程模型具有简单、高效的特点,最为重要的两个概念就是Map和Reduce.最基本的处理思想就是“分而治之,然后归约”。Hadoop会将一个大任务分解为可以同时执行的多个小任务,从而达到并行计算的目的。举个简单的例子,对于一个大型任务,单机处理需要1024分钟,而分解为1024个子任务并行执行就可在1分钟完成处理。在对处理的数据集的要求上,相比于传统关系数据库的结构化数据,MapReduce模型的Hadoop框架适合半结构化或非结构化的数据。 Hadoop通过自动分割将要执行的问题(程序)、拆解成Map(映射)和Reduce(化简)的方式,其分解过程的实质是将问题分为几个部分,划分为可以应用于程序的数据,再将数据分解,然后对分解的数据进行并行操作,在自动分割后通过Map程序将数据映射成不相关的区块,分配(调度)给大星的i十算机进行处理以达到分散运算的效果,再通过Reduce程序将结果汇总整合,输出开发者需要的结果。 Hadoop向用户提供了一个规范化的MapReduce编程接口,用户只需要编写Map和Reduce函数,这两个函数都是运行在键-值对基础上的,数据的切分,节点之间的通信协调等全部由Hadoop框架木身来负责。一般一个用户作业提交到Hadoop集群后会根据输入数据的大小并行启动多个Map进程及多个Reduce进程(也可以是0个或者1个)来执行.MapReduce也具有弹性适应性,小数据和大数据仅仅通过调整节点就可以处理,而不需要用户修改程序MapReduce模型处理流程如下图所示。 上图就是MapReduce的数据处理流程图,在Map之前会对输入的数据有split的过程,默认split就是写人数据时的逻辑块,每一个块对应一个split,一个split就对应一个Map进程,正是split保证了任务的并行效率。在Map之后还会有shuffe和sort的过程.shuffle简单描述就是一个Map的输出应该映射到哪个Reduce作为输入,sort就是指在Map运行完输出后会根据输出的键进行排序。这两个处理步骤对于提高Reduce的效率及减小数据传输的压力有很大的帮助。 从本质上讲MapReduce借鉴了函数式程序设计语言的设计思想,其软件实现是指定一个Map函数,把键值对(key/value)映射成新的键值对(key/value),形成一系列中间结果形式的键值对(key/value ),然后把它们传给Reduce(归约)函数,把具有相同中间形式key的value合并在一起。Map和Reduce。函数具有一定的关联性。其算法描述为: Map(k, v) ->list(k1,v1) Reduce(k1,list(v1)) ->list (v1) 在Map过程中将数据并行,即把数据用映射函数规则分开,而Reduce则把分开的数据用归约函数规则合在一起,即Map是个分的过程,Reduce则对应着合。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5080590.html,如需转载请自行联系原作者

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

Hadoop概念学习系列之Hadoop实现接口(十五)

Hadoop对于不同的开发者提供了三种接口: 第一种就是原生的Hadoop Java api接口; 第二种就是Hadoop Streaming接口,是通过标准输入/输出交互的,可以使用任何能操纵标准输人/输出的语言来编写MapReduce程序; 第三种就是Hadoop Pipes接口,专门针对C/C++的接。使用socket通信作为用户程序和Hadoop来进行交互。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5081055.html,如需转载请自行联系原作者

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

[Android学习笔记七] 设备管理服务示例开发

本文通过示例演示Android Device Policy管理的实现。 1.示例基本操作图 上图是本示例的主界面,通过应用程序来实现设备管理,本示例实现密码设置管理。 1.1 通过点击“启动设备管理器”按钮来激活设备管理 应用程序用通知设备管理启用,用户点击激活,应用程序具备设备管理能力。 1.2 通过点击“设置密码规则”按钮来设置锁屏密码的限制规则,要使用该策略需要在设备管理的使用策略列表中添加limit-password. 示例中调用了设置新密码的ACTION(DevicePolicyManager.ACTION_SET_NEW_PASSWORD),通过设置后,看以看到屏幕锁屏需要密码。 1.3 通过点击“修改密码”按钮则可以将文本框中的内容作为锁屏密码,该步骤可以通过程序完成。 调用DevicePolicyManager的重置密码方法(resetPassword),即可在应用程序中对锁屏密码进行重置。 2. 具体实现 实现上述整个示例需要: a.界面布局;实际应用中根据具体情况而定 b.DevicePolicyManager类的具体使用 c.DeviceAdminReceiver类的子类话,来实现具体广播事件的处理 d.AndroidManifest.xml文件中广播接收类的配置 c.应用程序中需要的设备管理策略列表 注:本示例代码使用了Butterknife框架。 2.1 示例程序界面(layout/activity_device_admin.xml) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <? xml version = "1.0" encoding = "utf-8" ?> < LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" android:layout_width = "match_parent" android:layout_height = "match_parent" android:background = "#f7f1f1" android:orientation = "vertical" android:padding = "15dp" > < LinearLayout android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_gravity = "center_horizontal" android:orientation = "horizontal" > < EditText android:id = "@+id/pwd_editText" android:layout_width = "0dp" android:layout_height = "wrap_content" android:layout_margin = "10dp" android:layout_weight = "3" android:hint = "6位数字" android:textColor = "@android:color/black" /> < Button android:id = "@+id/modify_pwd_button" android:layout_width = "0dp" android:layout_height = "wrap_content" android:layout_margin = "10dp" android:layout_weight = "1.5" android:text = "修改密码" /> </ LinearLayout > < Button android:id = "@+id/pwd_rule_set_button" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:text = "设置密码规则" /> < Button android:id = "@+id/device_admin_button" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:text = "启用设备管理" /> </ LinearLayout > 2.2 Activity类和自定义的DeviceAdminReceiver类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 package secondriver.sdk.activity; import android.app.Activity; import android.app.admin.DeviceAdminReceiver; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; import secondriver.sdk.R; /** *Author:secondriver *Created:2015/11/27 */ public class DeviceAdminActivity extends Activity{ @Bind (R.id.pwd_editText) public EditTextpwdEditText; private DevicePolicyManagermDevicePolicyManager; @Override protected void onCreate(BundlesavedInstanceState){ super .onCreate(savedInstanceState); setContentView(R.layout.activity_device_admin); ButterKnife.bind( this ); mDevicePolicyManager=(DevicePolicyManager)getSystemService(DEVICE_POLICY_SERVICE); } //单击启用设备管理按钮 @OnClick (R.id.device_admin_button) public void onClickDeviceButton(Buttonbutton){ Intentintent= new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, new ComponentName( this ,MyDeviceAdminReceiver. class )); intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "启动设备管理器" ); startActivityForResult(intent, 1 ); } //单击设置密码规则按钮 @OnClick (R.id.pwd_rule_set_button) public void onClickPwdRuleSetButton(Buttonbutton){ Intentintent= new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD); startActivityForResult(intent, 2 ); } //单击修改密码按钮 @OnClick (R.id.modify_pwd_button) public void onClickModifyPwdButton(Buttonbutton){ Stringpwd=pwdEditText.getText().toString(); ComponentNamereceiver= new ComponentName( this ,MyDeviceAdminReceiver. class ); boolean active=mDevicePolicyManager.isAdminActive(receiver); if (active){ boolean rs=mDevicePolicyManager.resetPassword(pwd,DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY); if (rs){ Toast.makeText( this , "密码修改成功" ,Toast.LENGTH_SHORT).show(); } else { Toast.makeText( this , "密码修改失败" ,Toast.LENGTH_SHORT).show(); } } else { Toast.makeText( this , "没有ActiveAdmin" ,Toast.LENGTH_SHORT).show(); } } @Override protected void onActivityResult( int requestCode, int resultCode,Intentdata){ switch (requestCode){ case 1 : if (resultCode==RESULT_OK){ Toast.makeText( this , "设备管理器开启成功" ,Toast.LENGTH_SHORT).show(); } else { Toast.makeText( this , "设备管理器开启失败" ,Toast.LENGTH_SHORT).show(); } break ; case 2 : if (resultCode==RESULT_OK){ Toast.makeText( this , "密码规则设置成功" ,Toast.LENGTH_SHORT).show(); } else { Toast.makeText( this , "密码规则设置失败" ,Toast.LENGTH_SHORT).show(); } break ; default : break ; } } //自定义的设备管理广播接收类,可以重写DeviceAdminReceiver中的方法,来实现具体功能 public static class MyDeviceAdminReceiver extends DeviceAdminReceiver{ /** *重写其中方法 *<p> *More */ @Override public void onDisabled(Contextcontext,Intentintent){ super .onDisabled(context,intent); //设备管理禁用 } @Override public void onEnabled(Contextcontext,Intentintent){ super .onEnabled(context,intent); //设备管理启用 } } } 2.3 配置设备管理接收者 1 2 3 4 5 6 7 8 9 < activity android:name = ".activity.DeviceAdminActivity" /> < receiver android:name = ".activity.DeviceAdminActivity$MyDeviceAdminReceiver" android:permission = "android.permission.BIND_DEVICE_ADMIN" > < meta-data android:name = "android.app.device_admin" android:resource = "@xml/device_admin" /> < intent-filter > < action android:name = "android.app.action.DEVICE_ADMIN_ENABLED" /> </ intent-filter > </ receiver > xml/device_admin内容: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <? xml version = "1.0" encoding = "utf-8" ?> < device-admin xmlns:android = "http://schemas.android.com/apk/res/android" > < uses-policies > <!--设置密码规则;控制屏幕锁的密码长度和允许的字符--> < limit-password /> <!--监视屏幕锁解锁尝试的次数;如果输入错误次数过多则锁定手机或者清除所有数据--> < watch-login /> <!--重置屏幕锁的密码;重新设置新的屏幕锁密码--> < reset-password /> <!--强制锁屏;控制屏幕锁屏的方式和时间--> < force-lock /> <!--擦除数据;恢复出厂设置清除说有数据--> < wipe-data /> <!--禁用相机;禁止使用所有设备摄像头--> < disable-camera /> <!--加密数据;对存储的应用数据进行加密--> < encrypted-storage /> <!--密码过期;强制用户更改屏幕锁密码的频率--> < expire-password /> </ uses-policies > </ device-admin > 示例生成apk,该应用具体了设备管理的功能。 本文转自 secondriver 51CTO博客,原文链接:http://blog.51cto.com/aiilive/1718579,如需转载请自行联系原作者

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

android学习记录(十三)Task 和 Activity 回退栈操作。

首先说一下Task是一个什么概念吧:Task是一个包括activity的列表。没 错。简单的说就是依照启动的先后来排队的一个队列。BackStack。就是回退栈的意思:那么有什么用?Back Stack是存储一个Task的实现方式,一个容器。它具有栈的特性:后进先出。 那么。根据什么来把activity指定给某个Task? ------默认情况下,依据activity的启动的顺序。增加A启动了B。那么B默认情况下就放到了 A的Task的BackStack里面啦。 当然,你也能够去改动这一个默认的行为。在以下的一些部分会讲述怎么去改动的啦。 须要注意的一点是:假如一个activity在一个新的task里启动且没有其它直接启动的方法(即不是Main,Launch的activity),然后按下Home键离开了该Task,然后通过启动图标来返回应用的话。是无法回到该activity的。 1.保存activity的属性和状态: 默认情况下,当activity脱离前台进入后台执行的时候,系统会自己主动保存它的配置信息,当用 户返回到activity的时候,能够自己主动的复原. 然而当过了比較长的一段时间后或者系统须要回收内存什么的,会清除掉它的配置信息,当 用户返回到该activity的时候会又一次的启动该activity. 那么这样的情况下假设要把曾经做的又一次再来一遍,这用户体验想想就认为不妥啊.那么我 们须要自己去保存和恢复activity的配置信息.then ,how? 实现onSaveInstanceState()方法,把所需的属性信息保存到bundle里. 在onCreate()方法里会有一个Bundle參数,假设不为空的话证明了之前是有一些信 信息是保存在这里的,我们就能够利用里面的信息去恢复用户原本处于的状态,这样子用户的体验是不是就好狠多啦?嘿嘿嘿嘿嘿 2.管理Task 如开头所说。我们能够改动系统的默认行为(即假设A启动了B。会把B放入A所在的Task和BackStack里)。那么,有两种方式能够做到: A.在startActivity(Intent intent)的intent中定义flag: intent.setFlags(flag); 系统会依据intent所定义的flag来对所被启动的activity来指定特定的Task。 B.在Manifest文件里该activity标签下的属性 taskAffinity launchMode allowTaskReparenting clearTaskOnLaunch alwaysRetainTaskState finishOnTaskLaunch 相同系统会依据属性里所定义的值来对被启动的activity进行指定task。 在这两种方式中,有一些效果是flag有而manifest文件没有的。相同也有一些效果 值是manifest文件有而flag所没有的。 当这两个值被同一时候设置的时候。flag的效果会覆盖launchMode所设置的效果。 以下,我们分别来对这两种不同方式的经常使用值来做简单的介绍。 一。定义启动activity的mode; 如果A>>B>>C A:定义manifest文件中launchMode属性: "standard"(默认值): 这是launchMode的默认值,假定C的launchMode为该值,若B启动C那么C也会放到B所属的Task里。C能够被初始化(即启动)多次,可属于不同的Task(即若与B不同Task的D启动了C,那么C新建一个实例放到D所在的Task里);一个Task里能够有多个C的实例(即若A>>B>>C>>A>>C,那么该任务的回退栈里有两个C的实例) "singleTop" 中文意思是:顶部唯一。假定C的launchMode的属性值为该值。 什么意思呢?就是说,在一个Task的顶部,仅仅能有一个C的实例,即若A>>B>>C然后在C里再次startActivityC,不会再创建一个C的实例,而是把该启动C的Intent传入到CActivity的onNewIntent()方法里。回退栈的结构依旧是:A>>B>>C而不是A>>B>>C>>C.这种话,就会出现一个随之产生的结果:不论什么时候C的实例都不会连续出现两次。相同与默认值类似,C也能够属于不同的Task(C无论任务是谁。它仅仅跟着动了它的activity在一起),单个Task里能够有多个C的实例。 (但不会出现连续) "singleTask" (中文:单个任务)假定activityC的launchMode值设置为该值。那么意味着不管何时C被启动,它都会在一个独立的Task里启动。 只是注意哦,独立的Task并非意味着新的Task。当C的独立的Task已经存在(即C被启动过)了,那么当再次调用C Activity的时候。就不会再创建了。而是把该Task移到前台来。(这也意味着,在同一时间。仅仅会有一个C的实例存在。) 注意:虽然C的Task并非与B的Task一致,但当用户按下backbutton的时候仍然能够回到B。 还有C的单独的Task里也能够有其它的Task,同一时候C并不一定要求是该任务的根activity。 "singleInstance". (中文:单例)假定C定义了该模式。 singleTask的mode也有单例效果,但该模式与singleTask不同的是,C所在的Task里仅仅能有它自己一个Activity,不会包括其它activity。(突然就想到:假设B启动了C。然后C启动了D,那么D是在还有一个新的Task里还是B所在的Task里呢?假设有人知道希望能够分享一下哈~) 这里有一个关于singleTask的图解嘿嘿,来自官方guide文档》》》》 图的下方有备注~自己琢磨琢磨吧。挺easy懂的了。 B.Intent的Flag属性 如果回退栈里有A>>B>>C (A启动B。B启动C): FLAG_ACTIVITY_NEW_TASK 效果与launchMode的singleTask属性一样。 当在C启动D的intent中定义了这个flag的时候。D会启动放置在一个新的Task里。即一个新的BackStack里。假设D已经被启动过一次然后到了后台执行(即A>>B>>C>>D>>E)再从E去启动D使用这一个flag的话,不会再次创建一个Task。而是把之前的D所在的Task恢复到前台,而D也会接收到一个Intent通过onNewIntent()方法。 @Override protectedvoid onNewIntent(Intent intent) { super.onNewIntent(intent); } FLAG_ACTIVITY_CLEAR_TOP 中文(清除activity的前方)如果C定义了该属性。 假设A>>B>>C>>D>>E。然后E启动activityC,那么并不会再创建一个C的实例,而是清除C前面的activity,恢复C的状态,显示C给用户看嘿嘿嘿,多霸气。 同一时候,manifest文件里launchMode并没有与之相应的属性值。 FLAG_ACTIVITY_SINGLE_TOP 与launchMode中的singleTop属性效果一样。 回退栈的清空 默认情况下,假设用户长时间不反悔该回退栈。那么因为种种原因(回收内存节省资源等等啦),会对该回退栈进行清空处理,仅仅留下一个最底部的activity留在栈内。所以当用户返回到这个Task时。仅仅会修复呈现栈最開始的一个activity。 相同,我们也能够对这样的默认的行为作出改动: alwaysRetainTaskState 当这个回退栈的根activity的该属性被设置为true时,那么不管用户隔了多长时间再回来,这个栈都不会被清除。 但要注意的是,必需要把该属性定义在回退栈的根activity才有效。 clearTaskOnLaunch 这个属性与alwaysRetainTaskState属性的效果刚好相反。 仅仅要用户一离开当前的Task。那么回退栈就会被清空仅仅留下根activity。 就算是刚离开又立即点击回来也是如此。相同该属性也必须定义在某个Task的根activity上才有效。 finishOnTaskLaunch 这个属性有点像clearTaskOnLaunch的属性效果,但与之不同的是它所作用的范围是单个activity(不论什么activity都行)而clearTaskOnLaunch的作用域是整个Task。被定义了该属性的activity会在用户离开所在Task之后被清除。(仅仅是清除Task里的这个activity。 taskAffinity属性及其用法 :这个。。感觉比較少用啊,。。(说实话就是我比較懒)假设想要了解一下的话自行查阅哈。 官方guide文档里的Taskand Back Stack里有的。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5370656.html,如需转载请自行联系原作者

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

Android开发学习笔记:Activity的生命周期浅析

1.Android系统中Activity作为Activity栈(Stack)被管理的,大家都知道栈的特点是先进后出,所以当前活动的Activity处于栈顶,之前非活动的Activity被压入栈底,等待是否可能被恢复为活动状态。 Android API中所提供的Activity生命周期图: 2.下面的整个Activity生命周期中的所有方法,我们可以根据程序的需要来覆盖相应的方法: publicclassActivityextendsApplicationContext{ //创建的时候调用 protectedvoidonCreate(BundlesavedInstanceState); //启动的时候调用 protectedvoidonStart(); //重新启动的时候调用 protectedvoidonRestart(); //恢复的时候调用 protectedvoidonResume(); //暂停的时候调用 protectedvoidonPause(); //停止的时候调用 protectedvoidonStop(); //销毁的时候调用 protectedvoidonDestroy(); } onCreate(Bundle savedInstanceState):创建activity时调用。设置在该方法中,还以Bundle的形式提供对以前储存的任何状态的访问! onStart():activity变为在屏幕上对用户可见时调用。 onResume():activity开始与用户交互时调用(无论是启动还是重新启动一个活动,该方法总是被调用的) onPause():activity被暂停或收回cpu和其他资源时调用,该方法用于保存活动状态的,也是保护现场,压栈。 onStop():activity被停止并转为不可见阶段及后续的生命周期事件时调用。 onRestart():重新启动activity时调用。该活动仍在栈中,而不是启动新的活动 onDestroy():activity被完全从系统内存中移除时调用 3.下面通过实例来测试Activity的生命周期中各个方法的调用情况,将Activity的所有方法都覆盖,主要用Log打印输出信息,并通过日志(LogCat)方式来观察运行结果。Log.v(String tag, String msg); //Verbose Log.d(String tag, String msg); //Debug Log.i(String tag, String msg); //Info Log.w(String tag, String msg); //Warning Log.e(String tag, String msg); //Error tag类似标签,可以是任意字符串,通常可以使用类名+方法名, 主要是用来在查看日志时提供一个筛选条件。 下面的实例是测试Activity的生命周期中各个方法的调用情况: MainActivity.java packagecom.android.TestAvtivity.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.util.Log; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ privateButtonbtn; privatestaticfinalStringTAG="MainActivity"; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //输出日志 Log.i(TAG,"MainActivityonCreate--->"); btn=(Button)findViewById(R.id.Button1); btn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //结束当前的Activity MainActivity.this.finish(); } }); } @Override //启动 protectedvoidonStart(){ super.onStart(); //输出日志信息 Log.i(TAG,"MainActivityonStart--->"); } @Override //重启 protectedvoidonRestart(){ super.onRestart(); //输出日志信息 Log.i(TAG,"MainActivityonRestart--->"); } @Override //恢复 protectedvoidonResume(){ super.onResume(); //输出日志信息 Log.i(TAG,"MainActivityonResume--->"); } @Override //暂停 protectedvoidonPause(){ super.onPause(); //输出日志信息 Log.i(TAG,"MainActivityonPause--->"); } @Override //停止 protectedvoidonStop(){ super.onStop(); //输出日志信息 Log.i(TAG,"MainActivityonStop--->"); } @Override //销毁 protectedvoidonDestroy(){ super.onDestroy(); //输出日志信息 Log.i(TAG,"MainActivityonDestroy--->"); } } 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:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试Activit生命周期" /> <Button android:id="@+id/Button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关闭Activity" /> </LinearLayout> 效果图: ①当启动程序时,日志的输出结果如下图所示,程序执行了onCreate()->onStart()->onResume三个方法。输出如下: MainActivity onCreate---> MainActivity onStart---> MainActivity onResume---> 注意:这里我是在选择了绿色的“+”,这时出现了下图的界面,之后我就在Filter Name上写入Test,by Log Tag上写入MainActivity,按OK保存,这时就能在LogCat上面筛选我们想要看到的信息了。 ②当按(返回键)或者按钮时,日志的输出结果如下图所示,程序先后调用了onPause( )->onStop( )->onDestory( )三个方法。 ③当按(Home键)时,日志的输出结果如下图所示,程序先后调用了onPause( )->onStop( )这两个方法,这时候应用程序并没有销毁。 ④当再次启动程序时,日志的输出结果如下图所示,程序先后调用了onRestart( )->onStart( )->onResume( )三个方法。 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/636913

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

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

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处、作者信息和本声明。否则将追究法律责任。 http://liangruijun.blog.51cto.com/3061169/732310 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 本文出自 “IT的点点滴滴” 博客,请务必保留此出处http://liangruijun.blog.51cto.com/3061169/732310 本文转自SharkBin博客园博客,原文链接:http://www.cnblogs.com/SharkBin/p/5437961.html,如需转载请自行联系原作者

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

开源中国iOS客户端学习——(十)搜索功能

开源中国社区团队基于开源项目GitLab开发了一款和GitHub一样的在线代码托管平台 Git @ OSC。并且开源客户端的源码在GitHub上不做更新,迁移到Git @OSC上了,欲了解更多请访问Git @ OSC官网http://git.oschina.net 客户端源码下载地址:http://git.oschina.net/oschina/iphone-app 回归正题,今天分析的是开源中国iOS客户端搜索功能涉及道一些知识,XML解析和动态加载表视图单元格; 在软件首页右上角有一个搜索按钮,点击进入搜索界面,当搜索的内容很多时我们下拉点击 “下面20项。。。”可以在加载20项,这些数据如何填充到表视图之中? 负责搜索功能的是search下的searchView类,xib控件已经已经做好布局,首先说下SearchView.h文件属性成员代表的作用; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #import <UIKit/UIKit.h> #import "SearchResult.h" #import "MBProgressHUD.h" @interface SearchView : UIViewController<UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate> { // 可变数组存放解析的数据 NSMutableArray * results; // 搜索的时候判断是否正在加载数据 BOOL isLoading; // 判断数据是否加载完毕 BOOL isLoadOver; // 记录表视图单元格应该加载数据总条数 int allCount; } @property (strong, nonatomic) IBOutlet UISegmentedControl *segmentSearch; @property (strong, nonatomic) IBOutlet UITableView *tableResult; @property (strong, nonatomic) IBOutlet UISearchBar *_searchBar; //根据搜索关键字在不同分类中进行搜索 - (IBAction)segementChanged:(id)sender; //搜索 -( void )doSearch; //清空上次搜索记录 -( void )clear; OK现在看看SearchView.m文件,如果搜索的内容不为空开始 dosearch方法,dosearch方法中使用了ASNetwork类库封装的post网络请求方法(关于AFNetwork post get请求方法请看http://blog.csdn.net/duxinfeng2010/article/details/8620901) 1 2 3 4 - ( void )postPath:(NSString *)path parameters:(NSDictionary *)parameters success:( void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:( void (^)(AFHTTPRequestOperation *operation, NSError *error))failure post请求无法获取它的url,但是可以取出请求成功返回来的数据,比如搜索iOS 返回的xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 <? xml version = "1.0" encoding = "UTF-8" ?> < oschina > < pagesize >20</ pagesize > < results > < result > < objid >18397</ objid > < type >software</ type > < title > <![CDATA[iOS应用开发模板 iOS Boilerplate]]> </ title > < url > <![CDATA[http://www.oschina.net/p/ios-boilerplate]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >18977</ objid > < type >software</ type > < title > <![CDATA[ ios-static-libraries]]> </ title > < url > <![CDATA[http://www.oschina.net/p/ios-static-libraries]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >23309</ objid > < type >software</ type > < title > <![CDATA[ 仿陌陌的ios客户端]]> </ title > < url > <![CDATA[http://www.oschina.net/p/momo-ios-app]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >22121</ objid > < type >software</ type > < title > <![CDATA[iOS任务管理器 cheddar-ios]]> </ title > < url > <![CDATA[http://www.oschina.net/p/cheddar-ios]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >22900</ objid > < type >software</ type > < title > <![CDATA[白宫网站 iOS 客户端 wh-app-ios]]> </ title > < url > <![CDATA[http://www.oschina.net/p/wh-app-ios]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >17045</ objid > < type >software</ type > < title > <![CDATA[iPhone操作系统 iOS]]> </ title > < url > <![CDATA[http://www.oschina.net/p/ios]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >25685</ objid > < type >software</ type > < title > <![CDATA[iOS 弹出菜单 MLPPopupMenu]]> </ title > < url > <![CDATA[http://www.oschina.net/p/mlppopupmenu]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >22803</ objid > < type >software</ type > < title > <![CDATA[iOS日历控件 PMCalendar]]> </ title > < url > <![CDATA[http://www.oschina.net/p/pmcalendar]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >24390</ objid > < type >software</ type > < title > <![CDATA[iOS 功能测试框架 calabash-ios]]> </ title > < url > <![CDATA[http://www.oschina.net/p/calabash-ios]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >24665</ objid > < type >software</ type > < title > <![CDATA[ iOS-Tree-Component]]> </ title > < url > <![CDATA[http://www.oschina.net/p/ios-tree-component]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >22217</ objid > < type >software</ type > < title > <![CDATA[ ios-calendar]]> </ title > < url > <![CDATA[http://www.oschina.net/p/ios-calendar]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >22380</ objid > < type >software</ type > < title > <![CDATA[ PaperFold-for-iOS]]> </ title > < url > <![CDATA[http://www.oschina.net/p/paperfold-for-ios]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >21763</ objid > < type >software</ type > < title > <![CDATA[ drupal-ios-sdk]]> </ title > < url > <![CDATA[http://www.oschina.net/p/drupal-ios-sdk]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >19628</ objid > < type >software</ type > < title > <![CDATA[iOS开发基础工具包 BaseAppKit]]> </ title > < url > <![CDATA[http://www.oschina.net/p/baseappkit]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >20637</ objid > < type >software</ type > < title > <![CDATA[iOS消息提醒库 TBHintView]]> </ title > < url > <![CDATA[http://www.oschina.net/p/tbhintview]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >21246</ objid > < type >software</ type > < title > <![CDATA[iOS 弹出式菜单 MGTileMenu]]> </ title > < url > <![CDATA[http://www.oschina.net/p/mgtilemenu]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >23498</ objid > < type >software</ type > < title > <![CDATA[iOS 的 Canvas 和 Audio 实现 Ejecta]]> </ title > < url > <![CDATA[http://www.oschina.net/p/ejecta]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >23968</ objid > < type >software</ type > < title > <![CDATA[样式化 iOS 应用 NUI]]> </ title > < url > <![CDATA[http://www.oschina.net/p/nui]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >20730</ objid > < type >software</ type > < title > <![CDATA[iOS/Android 矢量图形框架 TouchVG]]> </ title > < url > <![CDATA[http://www.oschina.net/p/touchvg]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > < result > < objid >22356</ objid > < type >software</ type > < title > <![CDATA[iOS日历控件 MACalendarUI]]> </ title > < url > <![CDATA[http://www.oschina.net/p/macalendarui]]> </ url > < pubDate ></ pubDate > < author ></ author > </ result > </ results > < notice > < atmeCount >0</ atmeCount > < msgCount >0</ msgCount > < reviewCount >0</ reviewCount > < newFansCount >0</ newFansCount > </ notice > </ oschina > <!-- Generated by OsChina.NET (init:0[ms],page:13[ms],ip:61.163.231.198) --> 要解析xm里数据必须熟悉xml文件各个节点之间关系 根节点oschina,它的子节点pagesize返回本次加载了几条数据,子节点results,results的子节点下20条result节点,我们主要获取result内容。然后就是最后面的子节点notice节点,存放用户的一些信息如动弹情况、收到消息、回复、粉丝;在post请求中用到了一个异常处理语句 @try @catch @finally @try{//执行的代码,其中可能有异常。一旦发现异常,则立即跳到catch执行。否则不会执行catch里面的内容}@catch{//除非try里面执行代码发生了异常,否则这里的代码不会执行}@finally{//不管什么情况都会执行,包括try catch 里面用了return ,可以理解为只要执行了try或者catch,就一定会执行 finally} 给dosearch添加了一些注释 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 -( void )doSearch { // 标记,表示正在加载数据中 isLoading = YES; NSString * catalog; // switch语句中根据Segment按钮集合中按钮索引,判断搜索哪一类内容,为下面的搜索API传参 switch (self.segmentSearch.selectedSegmentIndex) { case 0: catalog = @ "software" ; break ; case 1: catalog = @ "post" ; break ; case 2: catalog = @ "blog" ; break ; case 3: catalog = @ "news" ; break ; } //使用AFNetWork使用post方式从网络请求数据 [[AFOSCClient sharedClient] postPath:api_search_list parameters:[NSDictionary dictionaryWithObjectsAndKeys:_searchBar.text,@ "content" ,catalog,@ "catalog" ,[NSString stringWithFormat:@ "%d" , allCount/20],@ "pageIndex" ,@ "20" ,@ "pageSize" , nil] success:^(AFHTTPRequestOperation *operation, id responseObject) { // 取消searchBar的第一响应对象,键盘消失 [self._searchBar resignFirstResponder]; // 在没有内容之前tableView是没有任何内容的,所以隐藏掉 self.tableResult.hidden = NO; // 根据请求回来的数据判断当前用户释放登陆,需要获取用户一些信息 [Tool getOSCNotice2:operation.responseString]; // 上面属于请求数据是不回加载到视图控制器上,所以标记属性为NO isLoading = NO; // 再次从xml文件中请求数据,获取当前加载数据条数,数量 int count = [Tool isListOver2:operation.responseString]; allCount += count; // 将请求的xml内容给NSString对象 NSString *response = operation.responseString; NSLog(@ "response =%@" ,response); @ try { // 开始解析需要显示到表视图单元格对象中的数据 TBXML *xml = [[TBXML alloc] initWithXMLString:response error:nil]; TBXMLElement *root = xml.rootXMLElement; // 从次根节点获取根节点下内容 TBXMLElement *_results = [TBXML childElementNamed:@ "results" parentElement:root]; if (!_results) { isLoadOver = YES; [self.tableResult reloadData]; return ; } // 获取result节点下内容 TBXMLElement *first = [TBXML childElementNamed:@ "result" parentElement:_results]; if (!first) { isLoadOver = YES; [self.tableResult reloadData]; return ; } // 取出result节点下的节点 NSMutableArray * newResults = [[NSMutableArray alloc] initWithCapacity:20]; TBXMLElement *objid = [TBXML childElementNamed:@ "objid" parentElement:first]; TBXMLElement *type = [TBXML childElementNamed:@ "type" parentElement:first]; TBXMLElement *title = [TBXML childElementNamed:@ "title" parentElement:first]; TBXMLElement *url = [TBXML childElementNamed:@ "url" parentElement:first]; TBXMLElement *pubDate = [TBXML childElementNamed:@ "pubDate" parentElement:first]; NSString * pubDateStr = [TBXML textForElement:pubDate]; TBXMLElement *author = [TBXML childElementNamed:@ "author" parentElement:first]; // 取出节点中的值,赋给一个SearchResult对象属性 SearchResult * s = [[SearchResult alloc] initWithParameters:[[TBXML textForElement:objid] intValue] andType:[[TBXML textForElement:type] intValue] andTitle:[TBXML textForElement:title] andUrl:[TBXML textForElement:url] andPubDate:[pubDateStr isEqualToString:@ "" ] ? @ "" : [Tool intervalSinceNow:pubDateStr] andAuthor:[TBXML textForElement:author]]; // 将获取对象添加到可变数组 if (![Tool isRepeatSearch:results andResult:s]) { [newResults addObject:s]; } // 在循环之中 寻找下一个节点 直至找完 while (first) { first = [TBXML nextSiblingNamed:@ "result" searchFromElement:first]; if (first) { objid = [TBXML childElementNamed:@ "objid" parentElement:first]; type = [TBXML childElementNamed:@ "type" parentElement:first]; title = [TBXML childElementNamed:@ "title" parentElement:first]; url = [TBXML childElementNamed:@ "url" parentElement:first]; pubDate = [TBXML childElementNamed:@ "pubDate" parentElement:first]; author = [TBXML childElementNamed:@ "author" parentElement:first]; s = [[SearchResult alloc] initWithParameters:[[TBXML textForElement:objid] intValue] andType:[[TBXML textForElement:type] intValue] andTitle:[TBXML textForElement:title] andUrl:[TBXML textForElement:url] andPubDate:[Tool intervalSinceNow:[TBXML textForElement:pubDate]] andAuthor:[TBXML textForElement:author]]; // if (![Tool isRepeatSearch:results andResult:s]) { [newResults addObject:s]; } } // first = NULL 直接跳出 else { break ; } } // 如果搜索结果数据小雨20条,表示一个页面就可以加载完毕 if (newResults.count < 20) { isLoadOver = YES; } // 将解析数据添加道results之中 [results addObjectsFromArray:newResults]; // 刷新表示图内容 [self.tableResult reloadData]; } @ catch (NSException *exception) { [NdUncaughtExceptionHandler TakeException:exception]; } @finally { } // 请求失败 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [Tool ToastNotification:@ "网络连接故障" andView:self.view andLoading:NO andIsBottom:NO]; }]; // 刷新表视图单元内容 [self.tableResult reloadData]; } 在 [Tool getOSCNotice2:operation.responseString];解析的登陆用户一些信息 // Tool类中 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 + (OSCNotice *)getOSCNotice2:(NSString *)response { TBXML *xml = [[TBXML alloc] initWithXMLString:response error:nil]; TBXMLElement *root = xml.rootXMLElement; if (!root) { return nil; } TBXMLElement *notice = [TBXML childElementNamed:@ "notice" parentElement:root]; if (!notice) { [Config Instance].isLogin = NO; [[NSNotificationCenter defaultCenter] postNotificationName:@ "login" object:@ "0" ]; return nil; } else { [[NSNotificationCenter defaultCenter] postNotificationName:@ "login" object:@ "1" ]; [Config Instance].isLogin = YES; } TBXMLElement *atme = [TBXML childElementNamed:@ "atmeCount" parentElement:notice]; TBXMLElement *msg = [TBXML childElementNamed:@ "msgCount" parentElement:notice]; TBXMLElement *review = [TBXML childElementNamed:@ "reviewCount" parentElement:notice]; TBXMLElement *newFans = [TBXML childElementNamed:@ "newFansCount" parentElement:notice]; OSCNotice *oc = [[OSCNotice alloc] initWithParameters:[[TBXML textForElement:atme] intValue] andMsg:[[TBXML textForElement:msg] intValue] andReview:[[TBXML textForElement:review] intValue] andFans:[[TBXML textForElement:newFans] intValue]]; [[NSNotificationCenter defaultCenter] postNotificationName:Notification_NoticeUpdate object:oc]; return oc; } [Tool isListOver2:operation.responseString]; 用于也是解析数据,获取返回的数据条数,告诉table将要显示多少行cell,当把cell加载到最后的时候获取下面20项,或跟多,然后把这些数据存放道allcount里面,所以就有allCount += count Tool类中,解析返回一个数据 pagesize,显示多少行 1 2 3 4 5 6 7 8 + ( int )isListOver2:(NSString *)response { TBXML *xml = [[TBXML alloc] initWithXMLString:response error:nil]; TBXMLElement *root = xml.rootXMLElement; TBXMLElement *pageSize = [TBXML childElementNamed:@ "pagesize" parentElement:root]; int size = [[TBXML textForElement:pageSize] intValue]; return size; } 然后进入到try中又一次解析获取result里面数据,这里有请求了一次数据,有解析了一边,感觉这里处理的不是很好,同一个返回数据请求了三次,如果用户用的不是wifi就可能耗费流量浪费电量; 剩下的就是表示图加载数据了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // 如何加载完成,返回数据为空,返回1,这个单元格是显示一个提示,“查无结果” 如果返回不为空,返回results.count + 1 个显示结果,最后加 1 ,是显示加载数据超过20条的时候 点击 “下面20项”时加载更多数据 if (isLoadOver) { return results.count == 0 ? 1 : results.count; } else return results.count + 1; } //处理cell的行高 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (isLoadOver) { return results.count == 0 ? 62 : 50; } else { return indexPath.row < results.count ? 50 : 62; } } //处理tableView背景色 -( void )tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { cell.backgroundColor = [Tool getCellBackgroundColor]; } //定制单元格的显示内容 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (results.count > 0) { if (indexPath.row < results.count) { UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NormalCellIdentifier]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:NormalCellIdentifier]; } SearchResult * s = [results objectAtIndex:indexPath.row]; cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0]; cell.textLabel.text = s.title; if (self.segmentSearch.selectedSegmentIndex != 0) { cell.detailTextLabel.text = [NSString stringWithFormat:@ "%@ 发表于 %@" , s.author, s.pubDate]; } else { cell.detailTextLabel.text = @ "" ; } cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; return cell; } else { return [[DataSingleton Instance] getLoadMoreCell:tableView andIsLoadOver:isLoadOver andLoadOverString:@ "搜索完毕" andLoadingString:(isLoading ? loadingTip : loadNext20Tip) andIsLoading:isLoading]; } } // 如果搜索返回的数据为空 提示 查无结果 else { return [[DataSingleton Instance] getLoadMoreCell:tableView andIsLoadOver:isLoadOver andLoadOverString:@ "查无结果" andLoadingString:(isLoading ? loadingTip : loadNext20Tip) andIsLoading:isLoading]; } } //选中某一行的时候显示该条信息的详细内容 -( void )tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self._searchBar resignFirstResponder]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; int row = indexPath.row; if (row >= results.count) { if (!isLoading && !isLoadOver) { [self performSelector:@selector(doSearch)]; } } else { SearchResult * s = [results objectAtIndex:row]; if (s) { [Tool analysis:s.url andNavController:self.navigationController]; NSLog(@ "------%@" ,s.url); } } } 打开某一条信息,并查看其详细信息调用 analysis: andNavController:,该方法里针对传入URL,如果是站外连接 比如某个软件官网,直接跳转到该软件的官网上,如果是开源中国社区站内连接,就可能需要加载一些这条信息的评论详情如果检测道用户登陆给予用户品论权限和分享功能;具体实现如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 + ( BOOL )analysis:(NSString *)url andNavController:(UINavigationController *)navController { NSString *search = @ "oschina.net" ; //判断是否包含 oschina.net 来确定是不是站内链接 NSRange rng = [url rangeOfString:search]; if (rng.length <= 0) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]]; return NO; } //站内链接 else { url = [url substringFromIndex:7]; NSString *prefix = [url substringToIndex:3]; //此情况为 博客,动弹,个人专页 if ([prefix isEqualToString:@ "my." ]) { NSArray *array = [url componentsSeparatedByString:@ "/" ]; //个人专页 用户名形式 if ([array count] <= 2) { [Tool pushUserDetailWithName:[array objectAtIndex:1] andNavController:navController]; return YES; } //个人专页 uid形式 else if ([array count] <= 3) { if ([[array objectAtIndex:1] isEqualToString:@ "u" ]) { [Tool pushUserDetail:[[array objectAtIndex:2] intValue] andNavController:navController]; return YES; } } else if ([array count] <= 4) { NSString *type = [array objectAtIndex:2]; if ([type isEqualToString:@ "blog" ]) { News *n = [[News alloc] init]; n.newsType = 3; n.attachment = [array objectAtIndex:3]; [Tool pushNewsDetail:n andNavController:navController andIsNextPage:NO]; return YES; } else if ([type isEqualToString:@ "tweet" ]){ Tweet *t = [[Tweet alloc] init]; t._id = [[array objectAtIndex:3] intValue]; [Tool pushTweetDetail:t andNavController:navController]; return YES; } } else if (array.count <= 5) { NSString *type = [array objectAtIndex:3]; if ([type isEqualToString:@ "blog" ]) { News *n = [[News alloc] init]; n.newsType = 3; n.attachment = [array objectAtIndex:4]; [Tool pushNewsDetail:n andNavController:navController andIsNextPage:NO]; return YES; } } } //此情况为 新闻,软件,问答 else if ([prefix isEqualToString:@ "www" ]) { NSArray *array = [url componentsSeparatedByString:@ "/" ]; int count = [array count]; if (count>=3) { NSString *type = [array objectAtIndex:1]; if ([type isEqualToString:@ "news" ]) { int newsid = [[array objectAtIndex:2] intValue]; News *n = [[News alloc] init]; n.newsType = 0; n._id = newsid; [Tool pushNewsDetail:n andNavController:navController andIsNextPage:YES]; return YES; } else if ([type isEqualToString:@ "p" ]){ News *n = [[News alloc] init]; n.newsType = 1; n.attachment = [array objectAtIndex:2]; [Tool pushNewsDetail:n andNavController:navController andIsNextPage:NO]; return YES; } else if ([type isEqualToString:@ "question" ]){ if (count == 3) { NSArray *array2 = [[array objectAtIndex:2] componentsSeparatedByString:@ "_" ]; if ([array2 count] >= 2) { int _id = [[array2 objectAtIndex:1] intValue]; Post *p = [[Post alloc] init]; p._id = _id; [Tool pushPostDetail:p andNavController:navController]; return YES; } } else if (count >= 4) { // NSString *tag = [array objectAtIndex:3]; NSString *tag = @ "" ; if (array.count == 4) { tag = [array objectAtIndex:3]; } else { for ( int i=3; i<count-1; i++) { tag = [NSString stringWithFormat:@ "%@/%@" , [array objectAtIndex:i],[array objectAtIndex:i+1]]; } } NSString *tag2 = [tag stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; PostsView *pview = [PostsView new ]; pview.tag = tag; pview.navigationItem.title = [NSString stringWithFormat:@ "%@" , tag2]; [navController pushViewController:pview animated:YES]; return YES; } } } } // 根据一个URL打开一个网页 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@ "http://%@" , url]]]; return NO; } } 本文转自新风作浪 51CTO博客,原文链接:http://blog.51cto.com/duxinfeng/1205492,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

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

Nacos

Nacos

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

Rocky Linux

Rocky Linux

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

WebStorm

WebStorm

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

用户登录
用户注册