Android12个重要知识点(2)






9. Android开发进阶之NIO非阻塞包(一)
对于Android的网络通讯性能的提高,我们可以使用Java上高性能的NIO (New I/O) 技术进行处理,NIO是从JDK 1.4开始引入的,NIO的N我们可以理解为Noblocking即非阻塞的意思,相对应传统的I/O,比如Socket的accpet()、read()这些方法而言都是阻塞的。   NIO主要使用了Channel和Selector来实现,Java的Selector类似Winsock的Select模式,是一种基于事件驱动的,整个处理方法使用了轮训的状态机,如果你过去开发过Symbian应用的话这种方式有点像活动对象,好处就是单线程更节省系统开销,NIO的好处可以很好的处理并发,对于Android网游开发来说比较关键,对于多点Socket连接而言使用NIO可以大大减少线程使用,降低了线程死锁的概率,毕竟手机游戏有UI线程,音乐线程,网络线程,管理的难度可想而知,同时I/O这种低速设备将影响游戏的体验。   
NIO作为一种中高负载的I/O模型,相对于传统的BIO (Blocking I/O)来说有了很大的提高,处理并发不用太多的线程,省去了创建销毁的时间,如果线程过多调度是问题,同时很多线程可能处于空闲状态,大大浪费了CPU时间,同时过多的线程可能是性能大幅下降,一般的解决方案中可能使用线程池来管理调度但这种方法治标不治本。使用NIO可以使并发的效率大大提高。当然NIO和JDK 7中的AIO还存在一些区别,AIO作为一种更新的当然这是对于Java而言,如果你开发过Winsock服务器,那么IOCP这样的I/O完成端口可以解决更高级的负载,当然了今天Android123主要给大家讲解下为什么使用NIO在Android中有哪些用处。    
NIO我们分为几个类型分别描述,作为Java的特性之一,我们需要了解一些新的概念,比如ByteBuffer类,Channel,SocketChannel,ServerSocketChannel,Selector和SelectionKey。有关具体的使用,Android开发网将在明天详细讲解。网友可以在Android SDK文档中看下java.nio和java.nio.channels两个包了解。http://www.android123.com.cn/androidkaifa/695.html
了解下这种技术,看看在马上要做的项目中是否用得到
10. Android Theme和Styles内部定义解析
昨天我们讲到的有关在AndroidManifest.xml中定义Activity的theme方法来实现无标题的方法,在使用xml让你的Activity无标题方法 一文中讲到的,很多网友不明白为什么这样做,其实在Android123以前的文章中多次提到了styles样式定义方法,
今天Android开发网再次把一些网友回顾了解下android样式的内部定义。 在一个工程的res/values/theme.xml中我们可以方便的定义自己的风格主题,

比如下面的cwjTheme中我们使用了基于android内部的白色调的背景Theme.Light,
设置windowsNoTitle为true代表没有标题,背景颜色我们使用了android内部定义的透明, 同时设置listView控件的样式为cwjListView,xml样式代码如下:    <?xml version="1.0" encoding="utf-8"?>  <resources> 
<style name="cwjTheme" parent="android:Theme.Light">     <item name="android:windowNoTitle">true</item> 
   <item name="android:windowBackground">@android:color/transparent</item>     <item name="android:listViewStyle">@style/cwjListView</item>  </style>  
有关ListView控件我们自定义的风格就是修改下系统listview这个控件的每行分隔符样式,这里我们在工程下res/drawable文件夹下放一个图片名为list_selector图片,这样我们的cwjListView的代码可以这样写    <style name="cwjListView" parent="@android:style/Widget.ListView">       <item name="android:listSelector">@drawable/list_selector</item>     </style>  </resources>   
通过定义style可以设置更多,比如让cwjListView的字体颜色就加入textAppearance属性, 比如 
<item name="textAppearance">@android:style/TextAppearance</item>  等等。  
11.Android JSON解析示例代码
来自Google官方的有关Android平台的JSON解析示例,如果远程服务器使用了json而不是xml的数据提供,在Android平台上已经内置的org.json包可以很方便的实现手机客户端的解析处理。下面Android123一起分析下这个例子,帮助Android开发者需要有关 HTTP通讯、正则表达式、JSON解析、appWidget开发的一些知识。 
 
public class WordWidget extends AppWidgetProvider { //appWidget     @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,             int[] appWidgetIds) {
        context.startService(new Intent(context, UpdateService.class)); //避免ANR,所以Widget中开了个服务     }     
public static class UpdateService extends Service {         @Override
        public void onStart(Intent intent, int startId) {             // Build the widget update for today
            RemoteViews updateViews = buildUpdate(this);             
ComponentName thisWidget = new ComponentName(this, WordWidget.class);
            AppWidgetManager manager = AppWidgetManager.getInstance(this);             manager.updateAppWidget(thisWidget, updateViews);         }         
public RemoteViews buildUpdate(Context context) {
            // Pick out month names from resources             Resources res = context.getResources();
            String[] monthNames = res.getStringArray(R.array.month_names);              
Time today = new Time();
            today.setToNow();             
String pageName = res.getString(R.string.template_wotd_title, monthNames[today.month],
today.monthDay);









            RemoteViews updateViews = null;
            String pageContent = "";             
try {
                SimpleWikiHelper.prepareUserAgent(context);
                pageContent = SimpleWikiHelper.getPageContent(pageName, false);             } catch (ApiException e) {
                Log.e("WordWidget", "Couldn't contact API", e);             } catch (ParseException e) {
                Log.e("WordWidget", "Couldn't parse API response", e);             }             
 
//正则表达式处理,有关定义见下面的SimpleWikiHelper类
Pattern pattern = Pattern.compile(SimpleWikiHelper.WORD_OF_DAY_REGEX);            
Matcher matcher = pattern.matcher(pageContent); if (matcher.find()) {
updateViews = new  RemoteViews(context.getPackageName(),R.layout.widget_word);
                String wordTitle = matcher.group(1);
                updateViews.setTextViewText(R.id.word_title, wordTitle);
                updateViews.setTextViewText(R.id.word_type, matcher.group(2));
                updateViews.setTextViewText(R.id.definition, matcher.group(3).trim());                 
String definePage = res.getString(R.string.template_define_url, Uri.encode(wordTitle));
                Intent defineIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(definePage)); //这里是打开相应的网页,所以Uri是http的url,action是view即打开web浏览器
                PendingIntent pendingIntent = PendingIntent.getActivity(context, 0 /* no requestCode */, defineIntent, 0 /* no flags */);
                updateViews.setOnClickPendingIntent(R.id.widget, pendingIntent); //单击Widget打开Activity             
} else { 
 
                updateViews = new RemoteViews(context.getPackageName(), R.layout.widget_message);                 CharSequence errorMessage = context.getText(R.string.widget_error);                 updateViews.setTextViewText(R.id.message, errorMessage);             }
            return updateViews;         }    
     
@Override
        public IBinder onBind(Intent intent) {
            // We don't need to bind to this service             return null;         }     } }   
 
有关网络通讯的实体类,以及一些常量定义如下:   
public class SimpleWikiHelper {
    private static final String TAG = "SimpleWikiHelper";     
public static final String WORD_OF_DAY_REGEX =
            "(?s)\\{\\{wotd\\|(.+?)\\|(.+?)\\|([^#\\|]+).*?\\}\\}";     

private static final String WIKTIONARY_PAGE =
            "http://en.wiktionary.org/w/api.php?action=query&prop=revisions&titles=%s&" +             "rvprop=content&format=json%s";     
private static final String WIKTIONARY_EXPAND_TEMPLATES =             "&rvexpandtemplates=true";     
private static final int HTTP_STATUS_OK = 200;      private static byte[] sBuffer = new byte[512];      private static String sUserAgent = null;      
public static class ApiException extends Exception {
        public ApiException(String detailMessage, Throwable throwable) {             super(detailMessage, throwable);
        }         public ApiException(String detailMessage) {             super(detailMessage);         }     }     
 
public static class ParseException extends Exception {
        public ParseException(String detailMessage, Throwable throwable) {             super(detailMessage, throwable);         }     }     
 
public static void prepareUserAgent(Context context) {         try {
            // Read package name and version number from manifest             PackageManager manager = context.getPackageManager();
            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);             sUserAgent = String.format(context.getString(R.string.template_user_agent),                     info.packageName, info.versionName);         
} catch(NameNotFoundException e) {
            Log.e(TAG, "Couldn't find package information in PackageManager", e);         }     }    
public static String getPageContent(String title, boolean expandTemplates)             throws ApiException, ParseException {         String encodedTitle = Uri.encode(title);
        String expandClause = expandTemplates ? WIKTIONARY_EXPAND_TEMPLATES : "";         
String content = getUrlContent(String.format(WIKTIONARY_PAGE, encodedTitle, expandClause)); try {
       JSONObject response = new JSONObject(content);
       JSONObject query = response.getJSONObject("query");        JSONObject pages = query.getJSONObject("pages");
       JSONObject page = pages.getJSONObject((String) pages.keys().next());        JSONArray revisions = page.getJSONArray("revisions");        JSONObject revision = revisions.getJSONObject(0);
       return revision.getString("*");    } catch (JSONException e) {
            throw new ParseException("Problem parsing API response", e);         }     }  









    
protected static synchronized String getUrlContent(String url) throws ApiException {         if (sUserAgent == null) {
            throw new ApiException("User-Agent string must be prepared");         }         
HttpClient client = new DefaultHttpClient();
 
        HttpGet request = new HttpGet(url);
        request.setHeader("User-Agent", sUserAgent); //设置客户端标识         
try {
            HttpResponse response = client.execute(request);              
StatusLine status = response.getStatusLine();
            if (status.getStatusCode() != HTTP_STATUS_OK) {
                throw new ApiException("Invalid response from server: " +status.toString());             }             
HttpEntity entity = response.getEntity();
            InputStream inputStream = entity.getContent(); //获取HTTP返回的数据流          
ByteArrayOutputStream content = new ByteArrayOutputStream();              int readBytes = 0;
            while ((readBytes = inputStream.read(sBuffer)) != -1) {
                content.write(sBuffer, 0, readBytes); //转化为字节数组流             }             
 
return new String(content.toByteArray()); //从字节数组构建String
        } catch (IOException e) {
            throw new ApiException("Problem communicating with API", e);         } }

 
有关整个每日维基的widget例子比较简单,主要是帮助大家积累常用代码, 了解Android平台 JSON的处理方式,毕竟很多Server还是Java的。 
12.Android中使用定时器TimerTask类介绍
在Android平台中需要反复按周期执行方法可以使用Java上自带的TimerTask类, TimerTask相对于Thread来说对于资源消耗的更低,
除了使用Android自带的AlarmManager使用Timer定时器是一种更好的解决方法。  我们需要引入import java.util.Timer; 和 import java.util.TimerTask;  
private Timer  mTimer = new Timer(true); private TimerTask mTimerTask;      mTimerTask = new TimerTask()  {
      public void run()       {
       Log.v("android123","cwj");       }           };
     mTimer.schedule(mTimerTask, 5000,1000);  //在1秒后每5秒执行一次定时器中的方法,
      


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值