当前位置:  编程技术>移动开发
本页文章导读:
    ▪Hibernate遇到的有关问题        Hibernate遇到的问题设计Student、Teacher表 多端Student有外键关联Teacher 在做级联删除测试的时候出现一个很想不明白的问题:         Session session1 = sf.openSession();        Transaction tran = sessi.........
    ▪ Hibernate多对多操作方法        Hibernate多对多操作步骤== Hibernate_ManytoMany_(AssociationMapping之一) (一)   关联映射准备步骤:       1)Table加中间表,加关联字段。无需建立主外键约束。  建立<usr表>、<authorizatio.........
    ▪ 基于mjpg-streamer-r63的源码分析之:基础知识详细解释[1]       基于mjpg-streamer-r63的源码分析之:基础知识详细解释[一] *************************************************************************************************************************** 作者:EasyWave                       .........

[1]Hibernate遇到的有关问题
    来源: 互联网  发布时间: 2014-02-18
Hibernate遇到的问题

设计Student、Teacher表 多端Student有外键关联Teacher

在做级联删除测试的时候出现一个很想不明白的问题:

        Session session1 = sf.openSession();


       Transaction tran = session1.beginTransaction();


       Teacher t = new Teacher();

       t.setTid("4028803538c72b670138c72b68a30001");
     

      session1.delete(t);
  

      tran.commit();
  

     session1.flush();
   

      session1.close();
  
    }

结果只是把Teacher这条记录删掉了,在student表里的TID外键字段值删掉,并没有想象中删掉Student的关联记录

 

        Session session1 = sf.openSession();

 


       Transaction tran = session1.beginTransaction();


     

      Teacher t=(Teacher)session1.get(Teacher.class, "4028803538c72b670138c72b68a30001");

     

      session1.delete(t);
  

      tran.commit();
  

     session1.flush();
   

      session1.close();
  
    }

改成这种方式就OK......
     


    
[2] Hibernate多对多操作方法
    来源: 互联网  发布时间: 2014-02-18
Hibernate多对多操作步骤

== Hibernate_ManytoMany_(AssociationMapping之一)
(一)   关联映射准备步骤:
      1)Table加中间表,加关联字段。无需建立主外键约束。  建立<usr表>、<authorization表>、及中间表<userauth表>。
      2)关联映射实现:
               方案一)此时已有两个1对*,可以用【两个1对*】配置来实现。
               缺点:配置复杂。连表查询时,select语句生成多; 不建议采用。
               方案二)用【一个 *---*】,来直接配置实现。
               特点:只写一套映射配置----<usr.hbm.xml> + Usr PO────→<authorization.hbm.xml> + Authorization PO只涉及两个PO类、两个《 .hbm.xml》文件。
                           加了中间表,但并不加<中间表.hbm.xml> 和 PO类;
       3)先用工具,生成两个多端的单表配置; 
       4)两端PO添加关联属性集合

                   private Set auths = new HashSet();                 
                   private Set users = new HashSet();
        5)再添加 <表名.hbm.xml>中的关联映射配置:
              特点: 多对多 和 一对一 一样,两边配置都十分对称。
              本质:可以看到多对多其实就是一对多;<set、lazy=、cascade=、inverse=、<key等都是按1对多来走的;
                          一对一、多对多 两边配置都十分对称。
    
          <set name="auths" table="userauth"---中间表名
                  azy="true"
                   cascade="all"---六种
                   inverse="false"
                <key colume="userid"/>-----表中有关联字段时,设置此项,中间表关联本端的字段名
                <many-to-many column="authid"/>
           </set>
  
    ◇◇中间表的id,最好设置为自动增长;否则级联插入时,中间表的主键id,因为没法人工设置,只能自动使用缺省值,就只能插入一条;

(二)多对多的操作:
                  (1)级联插入
                         ---DAO:
 /**
  * 插入User PO记录,级联插入该用户拥有的权限PO记录;
  * @param usr---临时态User PO对象;
 */
 public void addUsr(Usr usr){
       Transaction tr=null;
       Session session=null;
       try{
              session=HibernateSessionFactory.getSession();
              tr=session.beginTransaction();
              session.save(usr);//将级联插入该用户拥有的所有权限authorization PO记录
              tr.commit();
         }catch(Exception e){
              e.printStackTrace();
         try{
              tr.rollback();
          }catch(HibernateException he){
               he.printStackTrace();
   }
  }finally{
   session.close();
  }
 }

      ---BO:张磊磊。
 public static void main(String[] args) {
         Usr usr=new Usr(); ------------先做好一个新用户;(临时态)
         usr.setAddress("changchun");
         usr.setName("zhangsan");
         usr.setMale("male");
         usr.setId(225);//主键,App设置;DB中为varchar 或 int;
        
         Authorization aut=new Authorization(); -----再做好几个该用户拥有的新权限;(临时态)
         aut.setColumnId(111);
         aut.setAuthorize(new Integer(123));
         aut.setInit(new Integer(124));
         aut.setId(1008); //主键,
        
         Authorization aut1=new Authorization();-----新权限;
         aut1.setColumnId(112);
         aut1.setAuthorize(new Integer(113));
         aut1.setInit(new Integer(114));
         aut1.setId(1009);
        
  //建立两种PO的关联;
         Set set1=usr.getAuthorization(); ---先获得关联属性集合Set;(HashSet)
         set1.add(aut);  //权限集合中加入权限PO;建立关联
         set1.add(aut1);
        
         UsrDAO usrdao=new UsrDAO();---调用DAO方法,实现级联插入;
         usrdao.addUsr(usr);
 }

 结果:插左PO记录,级联插入中间表记录,以及右PO记录;

 ▲ 结论:多对多和一对一 一样,可以只配置单向关联。

  =========联表查询=====        
        //没关联记录时,没显示。
        //故意插入几个关联记录,再试试。
        问:可以只配单边映射配置,只实现单向查询吗?

               i)写DAO内:《HibernateService.java》
                                                          [数据访问方法]             ducongan.

 public List listAllUsrCascadeAuthorization() throws HibernateException{
  List list = null;
  Session  session = null;
  Transaction tx = null;
  ..............................
  list = session.createQuery("from Usr").list();  //查出Usr PO对象,自动联表查出Authorization PO对象。
                               ━━━━━━━━━━━
  ..............................                  //是否级联操作、联表查询,从上层Hibernate API无法看出,关键在.hbm.xml中。
  return list;
 }
       注意:查出的list的意义。

      5)BO (main)中,写调用该DAO方法:
                List list= DAO对象.listAllUsrCascadeAuthorization();           

                Usr userpo=(Usr)list.get(0);   //这个是一个Usr PO对象。
                Set st=userpo.getAuths();          //取出该Usr PO对象中的关联属性Set
                //遍历HashSet,it.next(),取出的是该Usr PO的一个权限PO。                ----晒晒老知识:Set只能遍历,不易于单个读取。

 //注意:检索策略;User----Authorization;默认使用延迟检索;---所以,不要关闭Session;
      如果改为立即检索;---则可能提取出所有的权限对象;
   如果再配有反向的Authorization----User;且为立即检索,---则连锁效应可能提取大量无用的关联对象;

 

 作业:撰写代码实现查询,查出《usr表》中name='张局长' 的user用户,其所拥有的各个(或第一个)权限,和其他哪些用户同时拥有这些权限?
 要求:必须列出张局长拥有哪些权限,及其权限名;
            还要列出每个权限所有拥有者的用户名;

 答案:
 ---BO:
  UserDao userDao = new UserDao();
  User findUserByName = userDao.findUserByName("张局长");
  System.out.println("张局长的ID号: "+findUserByName.getId());
  Set auths = findUserByName.getAuths();  //▲延迟加载,关联集合其中PO为代理对象;
  //▲注意:因为是延迟加载,所以自动使用Hibernate实现的PersistenceSet,不能强制转换回HashSet;
  System.out.println("权限个数: "+auths.size());   //▲用到此PO时,临时加载;
  Iterator it = auths.iterator();
  while(it.hasNext()){
   Authorization az = (Authorization)it.next();  //◆取出一个权限对象; 用到此PO时,临时加载;
   System.out.println("==权限ID号为:"+az.getId());   //用到此PO属性时,临时加载属性值;
   System.out.println("权限号为:"+az.getAuth());
   //提取该权限的所有用户; 也是延迟加载;
   Set users = az.getUsers();//拿到该权限的用户集合;
   Iterator iterator = users.iterator();//遍历该用户集合;
   while(iterator.hasNext()){
    User user = (User)iterator.next(); //◆取出一个拥有该权限的用户; 用到此PO时,临时加载;
    System.out.println("\t拥有该权限的用户:"+user.getName()+"\t用户ID号: "+user.getId()); //用到此PO时,临时加载;
   }
  }
  //关闭Session;
  //如果后续还要使用该Session,进行其他Dao操作,则仅关闭该Session缓存,但并不使其消失;
  userDao.sessionClose();
  所有操作完毕后,无需Session,此时应关闭Session使其消失;
  userDao.closeSession();

         
 数据例子: 《user表》中,1号的张局长,《userauth表》中,拥有:10号、22号权限;
                               4号  赵科长,                也拥有:10号;
                               5号  刘。。,                ......:10号;
              《userauth》表
                                                                                                                             
       ┌───┬───┬───┐
       │ id      │ uid   │ auid  │
       ├───┼───┼───┤ 
       │  1      │         │          │
       ├───┼───┼───┤ 
       │  2      │  1     │  10    │
       ├───┼───┼───┤ 
       │  3      │  2     │  15    │
       ├───┼───┼───┤ 
       │  4      │  1     │  22    │
       ├───┼───┼───┤ 
       │  5      │         │          │
       ├───┼───┼───┤ 
       │          │         │          │
       ├───┼───┼───┤ 
       │          │  5     │  10   │
       ├───┼───┼───┤ 
       │          │  2     │  22    │
       └───┴───┴───┘

   结果:全部延迟加载,连表查询,用的是单表select语句实现。

                                                                                              
  总结:*-*的检索策略,与1-*的检索策略,相同;
  ━━━━━━━━━━━━━━━━━━
         延迟加载:lazy="true"
         立即加载:lazy="false" fetch="select"
         预先抓取:lazy="false" fetch="join"
            
 

 

 

 

             
                                  

 

 

 


 


    
[3] 基于mjpg-streamer-r63的源码分析之:基础知识详细解释[1]
    来源: 互联网  发布时间: 2014-02-18
基于mjpg-streamer-r63的源码分析之:基础知识详细解释[一]

***************************************************************************************************************************
作者:EasyWave                                                                                 时间:2012.07.27

类别:linux应用之mjpg-streamer分析                                            声明:转载,请保留链接

注意:如有错误,欢迎指正。这些是我学习的日志文章......

***************************************************************************************************************************

在mjpg-streamer的开源的网络视频服务器项目中,在代码中会经常用到线程,在linux下的线程thread,下面来详细的分析和学习一下linux系统下的线程,如果是在ARM嵌入式系统中的应用程序要用到线程thread的话,需要在文件系统将libpthread-0.9.30.1.so,当然这个版本是需要看具体的arm-linux的编译器版本中所包含的版本号,只需拷贝到文件系统下的lib文件夹中,同时还需要将lib的路径配置好,这样应用程序能够找到这个libpthread-0.9.30.1.so库。这样就不会出现错误了。
一:线程的建立和退出
相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,而且拥有自己的栈空间,拥有独立的执行序列。在串行程序基础上引入线程和进程是为了提高程序的并发度,从而提高程序运行效率和响应时间。线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程则正好相反。
通过pthread_create()函数来建立线程API 定义如下(POSIX线程相关的函数和变量定义都在头文件pthread.h):

int pthread_create(pthread_t  *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void * arg)

参数:
      thread:线程id返回值(无符号长整型数,bits/pthreadtypes.h);

      attr: 默认值设置为NULL。(bits/pthreadtypes.h定义了结构体pthread_atttr_t);
     属性值包括:
            可分离状态(detached state):PTHREAD_CREATE_JOINABLE(缺省值);PTHREAD_CREATE_DETACHED。
            调度策略(scheduling policy):SCHED_OTHER(正常、非实时,缺省值)、SCHED_RR(实时、轮转法)和SCHED_FIFO(实时、先入先出)。后两种调度策                   略仅对超级用户有效,可通过函数pthread_setschedparam()来改变。
            调度参数(scheduling parameter):一个sched_param的机构,仅有一个整形变量表示线程运行的优先级。这个参数仅当调度策略为实时(SCHED_RR 和                               SCHED_FIFO)时才有效,可通过函数pthread_setschedparam()来设置,缺省值为0。
            继承属性( inheritsched attribute ) :PTHREAD_EXPLICIT_SCHED ( 默认值) 和PTHREAD_INHERIT_SCHED,前者表示新线程使用显式指定调度策
               略和调度参数(即attr中的值),而后者表示继承调用者线程的值。
            范围(scope):表示线程间竞争CPU 的范围,也就是说线程优先级的有效范围。POSIX 的标准中定义了两个值:PTHREAD_SCOPE_SYSTEM 和                                                PTHREAD_SCOPE_PROCESS,前者表示与系统中所有线程一起竞争CPU 时间,后者表示仅与同进程中的线程竞争CPU 。目前LinuxThreads 仅实现了
               PTHREAD_SCOPE_SYSTEM 值。
            守护池大小(guard size):表示线程守护池的大小,该属性控制守护池(guard area)的大小,直接影响到线程堆栈。该属性能有效抑制线程堆栈指针的溢出。
            堆栈地址(stack address):创建的线程堆栈的起始地址,最小值为PTHREAD_STACK_SIZE。
            堆栈大小( stack size ) : 堆栈大小, 该大小不小于PTHREAD_STACK_SIZE,当然也受限于系统限制。


void * (*start_routine)(void *):指向线程函数的函数指针(仅含有一个void *类型的参数)。

*arg:arg是void *类型的变量,但它同样可以作为任意类型的参数传给start_routine()函数。


二:线程资源释放的方法

Linux程序设计中,创建线程时调用pthread_create()函数。第二个参数attr为线程属性指针,一般情况下,我们创建线程时,若对线程属性没有特殊要求,都将此参数设为NULL,也就是使用了线程的默认属性--分离状态(joinable,或称可接合状态)。接下来主线程必须在适当的时候调用pthread_join(),同步(join,或等待,同步)子线程,同时释放线程本身占用的资源;否则,线程资源将驻留内存,直到整个进程退出为止。若该进程不断的创建线程,则每创建一次线程都会导致内存资源的消耗,很明显,这已经构成了内存泄漏!

对于线程资源的释放,有两种实现方法:
(1) 线程创建时,默认属性是可接合的(joinable),那就需要主线程来等待,所以在创建这个线程后适当的地方必须调用pthread_join()来等待子线程结束执行,否则就会引起内存泄漏!调用pthread_join()来等待子线程执行结束,这是 Linux同步主线程和子线程的一种机制,同时释放子线程的资源(线程描述符和堆栈(thread descriptor and stack))。假如使用默认线程属性,即线程属性为joinable,而又没有调用pthread_join(),那么该进程退出前,所创建的线程占用的资源便不会被释放(kind of like a zombie process),因此造成内存泄漏。假如你不想或没有必要同步主线程和子线程,那么就把子线程属性设置为detached分离状态,那么子线程结束执行后会自行销毁其占用的资源
(2) 将线程属性设为分离状态(detached),这样子线程就属于“自灭”:子线程函数启动后跟主线程不再有“父子”关系(等待和被等待),退出线程时其资源会自动释放。注意:创建线程时,若属性参数为NULL,则线程属性默认为可接合的(joinable,即需要主线程等待的)。可以在线程创建时将其属性设为分离状态(detached),也可在线程创建后将其属性设为分离的(detached)

1):线程建立代码

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *print_msg_function( void *ptr );
int main(int argc, char *argv[])
{
    pthread_t thread1 , thread2;
    char *msg1 = "Thread 1" ;
    char *msa2 = "Thread 2" ;
    int iret1 , iret2;
    /* 创建两个线程执行相同的函数 */
    iret1 = pthread_create( &thread1, NULL, print_msg_function, (void*)msg1 );
    iret2 = pthread_create( &thread2, NULL, print_msg_function, (void*)msg2 );
    /* 等待线程完成 */
    pthread_join( thread1, NULL);
    pthread_join( thread2, NULL);
    printf("Thread 1 returns: % d\n" ,iret1 );
    printf("Thread 2 returns: % d\n" ,iret2 );
    exit(0);
}
void *print_msg_function( void *ptr )
{
    char *msg;
    msg = (char * )ptr;
    printf("% s \n" , msg);
}

编译运行:
编译:
C 编译器: cc -lpthread pthread 1 .c

C ++ 编译器: g++ -lpthread pthread 1 .c
运行:./a.out
结果:
Thread 1
Thread 2
Thread 1 returns: 0
Thread 2 returns: 0


2):线程设置为joinable

#include <pthread.h>
void* thread_function (void* thread_arg)
{
    /* 线程要完成的工作 */
    ……
    pthread_exit(“Exiting from the thread _function!”);
}
int main(int argc, char *argv[])
{
    pthread_t thr;
    void* thread_result;
    pthread_create (& thr, NULL, & thread_function, NULL);
    /* 主线程做的工作 */
    ……
    /* 等待线程结束退出 */
    pthread_join(thr, & thread_result);
    return 0;
}
3):线程设置为detached

/* 线程创建后,通过调用pthread_detach()来设置 */
#include <pthread.h>
void* thread_function (void* thread_arg)
{
     /* 线程要完成的工作 */
     ……
     pthread_exit(“Exiting from the thread _function!”);
}
int main(int argc, char *argv[])
{
     pthread_t thread;
     pthread_create(&thread, NULL, &thread_function, NULL);
     pthread_detach(thread); /* D o w ork here... */
     /* 主线程做的工作 */
     ……
     /* 不需要join等待线程退出 */
     return 0;
}

三:线程同步

尽管在Posix 中同样可以使用IPC 的信号量机制来实现互斥锁mutex功能,但显然semphore的功能过于强大了,在Posix 中定义了另外一套专门用于线程同步的mutex函数

1):互斥锁创建和注销

         POSIX定义了两种方法创建互斥锁,静态方式和动态方式:
         pthread_mutex_t  mutex = PTHREA D_M UTEX_IN ITIA LIZER ;
         int  pthread _mutex_init(pthread_mutex_t  *mutex, const pthread_mutex attr_t  *mutex_attr);
         int  pthread _mutex_destroy(pthread_mutex_t  *mutex);

参数:
*mutex:pthread_mutex_t结构体;
*mutex_attr:指定互斥锁属性(属性的问题,大家可以到网络上去搜索啦,这里不多将了),如果为NULL,则使用缺省属性。Linux 实现中,

用宏PTHREAD_MUTEX_INITIALIZER 静态初始化互斥锁;动态方式是采用pthread_mutex_init()函数来初始化互斥锁。销毁一个互斥锁即意味着释放它所占用的资源,且要求互斥锁当前处于开放状态。但在Linux 中,互斥锁并不占用任何资源,因此销毁互斥锁pthread_mutex_destroy()除了检查锁状态以外(锁定状态则返回EBUSY)没有
其他动作。

2):锁操作

锁操作主要包括加锁(调用函数pthread_mutex_lock())、解锁(调用函数pthread_mutex_unlock() ) 和测试加锁( 调用函数pthread_mutex_trylock())三个,不论哪种类型的锁,都不可能被两个不同的线程同时得到,而必须等待解锁。对于普通锁和适应锁,解锁者可以是同进程内任何线程;而检错锁则必须由加锁者解锁才有效,否则返回EPERM;对于嵌套锁,文档和实现要求必须由加锁者解锁。在同一进程中的线程,如果加锁后没有解锁,则任何其他线程都无法再获得锁。
        int pthread _mutex_lock(pthread_mutex_t   *m utex)
        int pthread _mutex_unlock(pthread_mutex_t   *m utex)
        int pthread _mutex_trylock(pthread_mutex_t   *m utex)
pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待。

线程锁操作示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *function_count(void);
pthread_mutex_t  mutex1 = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
int main(int argc, char *argv[])
{
    int rc1 , rc2;
    pthread_t thread1 , thread2;
    /* 创建两个独立的线程,分别都调用函数 function_count */
    if( (rc1=pthread_create( &thread1, NULL,(void *)function_count, NULL)) )
    {
         printf("Thread creation failed : % d\n" , rc1 );
    }
    if( (rc2=pthread_create( &thread2, NULL,(void *)function_count, NULL)) )
    {
        printf("Thread creation failed : % d\n" , rc2);
    }
    /* 等待线程结束 */
    pthread_join( thread1, NULL);
    pthread_join( thread2, NULL);
    exit(0);
}
void *function_count(void)
{
    pthread_mutex_lock( &mutex1 );
    counter++;
    pthread_mutex_unlock( &mutex1 );
    printf("C ounter value: % d\n" ,counter);
}

四:条件变量

条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待“条件变量的条件成立”而挂起;另一个线程使“条件成立”(给出条件成立信号)。为了防止竞争,条件变量总是和互斥锁结合起来使用。

1):POSIX定义了两种方法创建条件变量,静态方式和动态方式:
       pthread_cond_t cond = PTH READ_COND_INITIA LIZER;
       int pthread _cond_init(pthread_cond_t  *cond, pthread_condattr_t  *cond_attr);
       int pthread _cond_destroy(pthread_cond_t  *cond);
参数:
*cond: pthread_cond_t的结构体;
*cond_attr:指定条件变量属性。尽管POSIX标准中为条件变量定义了属性,但在LinuxThreads中没有实现,因此cond_attr值通常为NULL,且被忽略。Linux实现中,用宏PTHREAD_COND_INITIALIZER静态初始化条件变量;动态方式是采用pthread_cond_init()函数来初始化条件变量。注销一个条件变量需要调用pthread_cond_destroy(),只有在没有线程等待该条件变量时才能注销该条件变量,否则返回EBUSY。因为Linux实现的条件变量没有分配什么资源,所以注销动作只包括检查是否有等待线程。

2):条件变量的等待和激发
条件变量的等待条件有两种方式:无条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),其中计时等待方式在给定时刻前条件没有满足,则返回ETIMEOUT,结束等待。其中abstime以与time()系统调用相同意义的绝对时间形式出现,0表示格林尼治时间1970年1月1日0时0分0秒。

int pthread _cond_wait(pthread_cond_t  *cond, pthread_mutex_t  *m utex)
int pthread _cond_timedwait(pthread_cond_t  *cond, pthread_mutex_t  *m utex, const struct tim espec *abstim e)
int pthread_cond_signal(pthread_cond_t  *cond)
int pthread_cond_broadcast(pthread_cond_t  *cond)
无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求条件等待pthread_cond_wait()(或pthread_cond_timedwait()。mutex互斥锁必须为普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),而且调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock())。在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁;条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入
pthread_cond_wait()后的解锁动作对应(实际上pthread_cond_wait()完成的操作包括:--解锁--挂起等待--加锁--,与pthread_cond_wait()前后的加锁、解锁正好对应)。
激发条件有两种形式:pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;而pthread_cond_broadcast()则激活所有等待线程。

具体的实例这个就不说了,自己可以到网上去搜索。但主要的一点是:为了防止竞争,条件变量总是和互斥锁结合起来使用。这个在mjpg-streamer的代码中得到了体现!

 


    
最新技术文章:
▪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