当前位置:  编程技术>移动开发
本页文章导读:
    ▪Fragment的使用与学习及使用过程中遇到的有关问题        Fragment的使用与学习及使用过程中遇到的问题 一直以来大概做带有导航类的应用的时候,都是使用TabActivity,但是,最新的SDK把TabActivity标成了deprecated,那只能重新寻找替代方案了,目前网上.........
    ▪ Toast跟Looper。Handler消息循环机制 ( Can't create handler inside thread that has not called Looper.prepare)        Toast和Looper。Handler消息循环机制 ( Can't create handler inside thread that has not called Looper.prepare)(1) Looper类别用来为一个线程开启一个消息循环。默认情况下Android中新诞生的线程是没有开启消息循环.........
    ▪ 6410SD卡起动流程       6410SD卡启动流程1.开始启动一个最小系统minifs_sd 2.然后启动busybox文件系统 lrwxrwxrwx  1 root root    11  7月  5  2011 linuxrc -> bin/busybox 3.执行etc/init.d/rcS文件 #!/bin/sh rm -f /var/run/dbus/* rm -rf /tmp/.*.........

[1]Fragment的使用与学习及使用过程中遇到的有关问题
    来源: 互联网  发布时间: 2014-02-18
Fragment的使用与学习及使用过程中遇到的问题
一直以来大概做带有导航类的应用的时候,都是使用TabActivity,但是,最新的SDK把TabActivity标成了deprecated,那只能重新寻找替代方案了,目前网上说的方案都是很混乱的

Fragment翻译过来叫碎片,但是我个人觉得可以理解为具有生命周期的View

由于Fragment是3.0以后的东西,对于适应低版本,那我们只能使用谷歌官方提供的android-support-v4.jar这个包了,最快捷的办法就是右击工程名,选择Android Tools——add support library...,即可添加这个包了

由于3.0以下的Activity里面没有对Fragment的支持,所以选择继承android-support-v4.jar包中的FragmentActivity,其功能跟3.0及以后的版本的Activity的功能一样

 DEMO下载:

FragmentTest.zip

底部导航加顶部导航,使用FragmentTabHost,Fragmetn,FragmentActivity组成,代码已经打包上传了

1、首先,底部导航的实现,FragmentTabHost和以前的TabHost的区别就是增加了对Fragment的支持,这里的实现和其他使用TabActivity是一样的,只是选项卡的切换已经从activity变成fragment了

2、这里主要讲一下顶部导航的实现,为了让大家对fragment更好的理解,这里我没有采用FragmentTabHost,而是放了三个Button

 

?
package com.yyb.fragmenttest;
 
import android.os.Bundle;
import android.support.v4.app.FragmentTabHost;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
 
public class Fragment1 extends BaseFragment implements OnClickListener{
 
    public static BaseFragment newInstance(int index) {
        BaseFragment fragment = new Fragment1();
        Bundle args = new Bundle();
        args.putInt("index", index);
        fragment.setArguments(args);
        fragment.setIndex(index);
        return fragment;
    }
 
    private View layoutView;
    private FragmentTabHost mTabHost;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
 
        layoutView = inflater.inflate(R.layout.fragment_tabs, null);
         
        layoutView.findViewById(R.id.button1).setOnClickListener(this);
        layoutView.findViewById(R.id.button1).setSelected(true);
        layoutView.findViewById(R.id.button2).setOnClickListener(this);
        layoutView.findViewById(R.id.button3).setOnClickListener(this);
 
        if(savedInstanceState ==null){
            BaseFragment fragment = (BaseFragment)getChildFragmentManager().findFragmentByTag(0+"");// getActivity().getSupportFragmentManager().findFragmentByTag(index+"");
            if(fragment==null){
                init(0);
            }
        }
         
        return layoutView;
    }
     
    private void init(int index) {
        FragmentTransaction ft = getChildFragmentManager().beginTransaction();
        ft.add(R.id.realtabcontent, Fragment11.newInstance(index) ,index+"");//将得到的fragment 替换当前的viewGroup内容,add则不替换会依次累加
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);//设置动画效果
        ft.commit();//提交
    }
 
    @Override
    public void onClick(View v) {
         
        allNoSelect();
         
        switch (v.getId()) {
        case R.id.button1:
            placeView(0);
            break;
        case R.id.button2:
            placeView(1);
            break;
        case R.id.button3:
            placeView(2);
            break;
        default:
            break;
        }
         
        v.setSelected(true);
    }
 
    private void allNoSelect() {
        layoutView.findViewById(R.id.button1).setSelected(false);
        layoutView.findViewById(R.id.button2).setSelected(false);
        layoutView.findViewById(R.id.button3).setSelected(false);
    }
 
    public void placeView(int index){
        BaseFragment fragment = (BaseFragment)<span style="color: #ff0000;">getChildFragmentManager()</span>.findFragmentByTag(index+"");// getActivity().getSupportFragmentManager().findFragmentByTag(index+"");
        //得到一个fragment 事务(类似sqlite的操作)
        FragmentTransaction ft = getChildFragmentManager().beginTransaction();
        if (fragment == null ) {
            switch (index) {
            case 0:
                fragment = Fragment11.newInstance(index);
                return;
            case 1:
                fragment = Fragment11.newInstance(index);
                break;
            case 2:
                fragment = Fragment11.newInstance(index);
                break;
            default:
 
                return;
            }
 
        }
        ft.replace(R.id.realtabcontent, fragment,index+"");//将得到的fragment 替换当前的viewGroup内容,add则不替换会依次累加
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);//设置动画效果
        ft.addToBackStack(null);
        ft.commit();//提交
 
    }
}

  这里有个FragmentTransaction(事务),这个是Fragment切换的核心类,它有两个方法:replace,add,一个是替换Fragment,一个是添加Fragment,两者的区别是:replace=remove掉旧fragment,add新的fragment

FragmentManager(碎片管理器),用来管理当前Activity中所有的Fragment

每次替换或者添加后,都要commit一样,才能算一个完整的事务,这里用了Fragment嵌套,还要注意一个问题,由于我当时没注意,导致想了好久才找出问题的原因所在,如果你是嵌套了Fragment,那么使用FragmentManager的一定要注意你当前的Fragment是属于嵌套的fragment还是顶层的Fragment,如果是顶层Fragment,那么你调用FragmentManager的时候,应该这样写getActivity().getSupportFragmentManager(),如果是嵌套的fragment那么应该这样写getChildFragmentManager()

 Fragment基础:http://www.cnblogs.com/TerryBlog/archive/2012/02/17/2355753.html


    
[2] Toast跟Looper。Handler消息循环机制 ( Can't create handler inside thread that has not called Looper.prepare)
    来源: 互联网  发布时间: 2014-02-18
Toast和Looper。Handler消息循环机制 ( Can't create handler inside thread that has not called Looper.prepare)

(1) Looper类别用来为一个线程开启一个消息循环。默认情况下Android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环)

Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。


(2) 通常是通过Handler对象来与Looper交互的。Handler可看做是Looper的一个接口,用来向指定的Looper发送消息及定义处理方法。

默认情况下Handler会与其被定义时所在线程的Looper绑定,比如,在主线程中定义,其是与主线程的Looper绑定。

mainHandler = new Handler() 等价于new Handler(Looper.myLooper()).

Looper.myLooper():Return the Looper object associated with the current thread 获取当前进程的looper对象。

还有一个类似的 Looper.getMainLooper() 用于获取主线程的Looper对象。


(3) 在非主线程中直接new Handler() 会报如下的错误:

E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。

 

(4) Looper.loop(); 让Looper开始工作,从消息队列里取消息,处理消息。

注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。

 

(5) 基于以上知识,可实现主线程给子线程(非主线程)发送消息。

 

Toast或者Dialog中都有一个Handler的成员变量,在初始化时都会跟着初始化,而Toast或者Dialog中的Handler都需要一个Looper,所以需要在包含该Toast或者Dialog的线程中(如下面的Timer线程)初始化Looper。Looper.prepare();

问题代码:

Java代码  
  • private Handler myHandler = new Handler() {   
  •         public void handleMessage(Message msg) {   
  •                                 Timer timer = new Timer();   
  •                 timer.schedule(new TimerTask() {   
  •                     @Override  
  •                     public void run() {   
  •                         InputMethodManager m = (InputMethodManager) editText   
  •                                 .getContext().getSystemService(   
  •                                         Context.INPUT_METHOD_SERVICE);   
  •                         m.showSoftInput(editText, 0);   
  •                         //   
  •                         Looper.prepare();   
  •                         Toast.makeText(Main.this, "show", Toast.LENGTH_LONG).show();   
  •                         Looper.loop();   
  •                     }   
  •                 }, 1000);   
  •                 }   
  • }  
  • private Handler myHandler = new Handler() {
    		public void handleMessage(Message msg) {
                                    Timer timer = new Timer();
    				timer.schedule(new TimerTask() {
    					@Override
    					public void run() {
    						InputMethodManager m = (InputMethodManager) editText
    								.getContext().getSystemService(
    										Context.INPUT_METHOD_SERVICE);
    						m.showSoftInput(editText, 0);
    						//
    						Looper.prepare();
    						Toast.makeText(Main.this, "show", Toast.LENGTH_LONG).show();
    						Looper.loop();
    					}
    				}, 1000);
                    }
    }

     

     

    Toast 和 Looper,一个属于 android.widget,一个属于 android.os,两个貌似联系不怎么紧密的类,却通过下面这个异常联系到了一起:

    Java代码  
  • E/AndroidRuntime( 1819): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()   
  • E/AndroidRuntime( 1819):        at android.os.Handler.<init>(Handler.java:121)   
  • E/AndroidRuntime( 1819):        at android.widget.Toast.<init>(Toast.java:68)   
  • E/AndroidRuntime( 1819):        at android.widget.Toast.makeText(Toast.java:231)  
  • E/AndroidRuntime( 1819): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    E/AndroidRuntime( 1819):        at android.os.Handler.<init>(Handler.java:121)
    E/AndroidRuntime( 1819):        at android.widget.Toast.<init>(Toast.java:68)
    E/AndroidRuntime( 1819):        at android.widget.Toast.makeText(Toast.java:231)
    

     

    Handler.java:121

    Java代码  
  • 119        mLooper = Looper.myLooper();   
  • 120        if (mLooper == null) {   
  • 121            throw new RuntimeException(   
  • 122            "Can't create handler inside thread that has not called Looper.prepare()");}  
  • 119        mLooper = Looper.myLooper();
    120        if (mLooper == null) {
    121            throw new RuntimeException(
    122            "Can't create handler inside thread that has not called Looper.prepare()");}

     

    Toast.java:68 ——>成员变量,在初始化时会跟着初始化

    Java代码  
  • 68    final Handler mHandler = new Handler();  
  • 68    final Handler mHandler = new Handler();

    由以上的错误信息可以看出:程序要创建 handler,但是发现Looper.prepare还没有被调用。通过 Android SDK 中的Reference可以看到,Looper、Handler 的调用是非常有讲究的,如下面示例代码:

     

    Java代码  
  • class LooperThread extends Thread {   
  •     public Handler mHandler;   
  •     
  •     public void run() {   
  •         Looper.prepare();   
  •         mHandler = new Handler() {   
  •             public void handleMessage(Message msg) {   
  •                 // process incoming messages here   
  •             }   
  •         };   
  •         Looper.loop();   
  •     }   
  • }  
  • class LooperThread extends Thread {
        public Handler mHandler;
     
        public void run() {
            Looper.prepare();
            mHandler = new Handler() {
                public void handleMessage(Message msg) {
                    // process incoming messages here
                }
            };
            Looper.loop();
        }
    }

     言归正题,继续寻找 Toast、Looper 和 Handler 三者之间的联系,也许谜底就能解开了。欲揭谜底,从源码入手是一条捷径。

    Toast.java 的第231行的代码是创建一个新的Toast实例,而实例化的过程中,就需要执行第68行,也就是声明并创建Handler(成员变量)的实例。那么来看Handler.java的第121行到底做了什么,如下所示:

    Java代码  
  • 119        mLooper = Looper.myLooper();   
  • 120        if (mLooper == null) {   
  • 121            throw new RuntimeException(   
  • 122            "Can't create handler inside thread that has not called Looper.prepare()");}  
  • 119        mLooper = Looper.myLooper();
    120        if (mLooper == null) {
    121            throw new RuntimeException(
    122            "Can't create handler inside thread that has not called Looper.prepare()");}

     到此,距离真相的解开近了一大步,既然抛出了 RuntimeException,那么 mLooper 肯定是 null,但是为什么 Looper.myLooper() 会返回 null?继续进入到 Looper.java 中寻根究底。

     

    Java代码  
  • /**  
  •  * Return the Looper object associated with the current thread.  Returns  
  •  * null if the calling thread is not associated with a Looper.  
  •  */  
  • public static final Looper myLooper() {   
  •     return (Looper)sThreadLocal.get();   
  • }  
  • /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static final Looper myLooper() {
        return (Looper)sThreadLocal.get();
    }

     以上就是 myLooper() 方法的真实面貌,通过注释可以看出问题的真正原因在于当前线程并没有绑定 Looper,返回为 null 是正确但非正常的结果。

     


        
    [3] 6410SD卡起动流程
        来源: 互联网  发布时间: 2014-02-18
    6410SD卡启动流程

    1.开始启动一个最小系统minifs_sd

    2.然后启动busybox文件系统

    lrwxrwxrwx  1 root root    11  7月  5  2011 linuxrc -> bin/busybox

    3.执行etc/init.d/rcS文件

    #!/bin/sh
    
    rm -f /var/run/dbus/*
    rm -rf /tmp/.*
    rm -rf /tmp/*
    
    #/bin/sh /etc/init.d/modules
    
    mount -a
    /sbin/mdev -s
    #hwclock -sl
    #mkfs.ext3 /dev/ram0
    #mount /dev/ram0 /tmp
    #mount -t sysfs none /sys
    /sbin/syslogd
    #/usr/sbin/telnetd
    
    #** install system **#
    /bin/sh /minifs_sh/install_cx_ctrl.sh&
    

    4.执行rcS文件内的install_cx_ctrl.sh

    #!/bin/sh
    
    ##############################################################
    #Todo on led for start
    
    /bin/mount /dev/mmcblk0p1 /mnt/sd
    
    echo "******** write backup kerner ********"
    /usr/sbin/flash_eraseall /dev/mtd1
    /usr/sbin/nandwrite -p /dev/mtd1 /mnt/sd/zImage*
    echo "******** write use kerner ********"
    /usr/sbin/flash_eraseall /dev/mtd2
    /usr/sbin/nandwrite -p /dev/mtd2 /mnt/sd/zImage*
    
    echo "******** write minifs ********"
    /usr/sbin/ubiformat /dev/mtd3 -f /mnt/sd/minifs_ubi*
    echo "******** write userdata ********"
    /usr/sbin/ubiformat /dev/mtd4 -f /mnt/sd/user_data_ubi*
    echo "******** write rootfs ********"
    /usr/sbin/ubiformat /dev/mtd5 -f /mnt/sd/rootfs_ubi*
    
    sync
    
    #Todo off led for end
    echo "*** OK ***"
    poweroff
    
    ##############################################################
    

    5.然后挂接文件执行安装程序



        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3