android 小结

Android学习心得和小总结

最近学习的一些小知识进行一下小总结:

1.1  surface的使用

使用surface时,包含了三个类的使用,分别是surfacesurfaceViewSurfaceHolder.

(1)Sueface:每一个surface在系统内部都对应了一段单独的视频缓冲区,surface就是这段缓冲区的一个类描述,可以通过surface提供的方法直接给这段缓冲区上绘图。

(2)SurfaceHolder类:该类是一个接口,主要是抽象出用于控制其对应的surface的标准方法。

(3)surfaceView类:surface本身并不是和GUI协同工作的,GUI需要为应用程序单独分配一段显示区,而这段显示区在一定程度上还要受到GUI的管理,比如,创建,销毁显示区;同时该显示区在一定程度上还需要和其他视图之间具有某种联系,以备GUI重新绘制界面时所需,而surface本身是一段显示缓冲区,内部并不具备这些操作的属性,surfaceView就是为满足这些操作而设计的。

3者的关系可如下所示:

GUI系统——>surfaceView——>surface

          应用程序——>surfaceHolder——>surface

GUI系统通过surfaceView来操作surface,而应用程序则是通过surfaceHolder来操作surface,一般情况下,无论是应用程序还是系统,都不直接调用surface这个接口。

  从单纯绘制界面的角度来看surface,在标准的GUI视图中,要绘制对应的界面只能在onDraw()方法中,因为只有在onDraw()方法中才能得到画布canvas对象。对于surface来讲,处于应用程序的考虑,子程序可以获得一个独立的surface对象,可以随时任意的绘制界面。因此surface有一个获取画布的接口,lockCanvas(),该方法返回此surface对应的画布,子程序是可以自由的享受这个surface,满足应用的界面需求。

使用surface的大多数场合是游戏开发,因为在游戏开发中,往往需要一些特别地界面元素,包括图形,变换和动画等内容。如何在surface上绘图:::

声明surface,可以在layout.xml文件中使用<surfaceView>关键字定义一个Surface对象,就像是用Button定义一个按钮一样,在xml中声明一个surface以后,调用SetContentView()方法创建该对象时,系统不会立即创建,即surface的创建时异步的,只有当surface创建好之后,用户才能使用该surface,子程序绘制surface时,一般通过surfaceHolder对象,每个surface对应一个Holder,surface创建好后,会回调对应的Holder对象定义的回调函数,这就是SurfaceHolder.Callback接口。

该接口包含了三个方法,分别是:

SurfaceCreated(),surface创建好后,会调用该函数,一般可以在干函数内部设置一个系统变量,用于标识surface是否创建好。

Public void surfaceCreated(SurfaceHolder  holder){

             msurfaceExsit=true;

}

surfaceChanged(),surface的界面大小改变时,调用该方法。

surfaceDestroy();surface对象被销毁时时,调用该方法。

在实际的游戏当中,往往会启动另一个线程用以控制surface内部的显示和用户交互,而在创建该线程时,只需要传递surface对应的surfaceHolder即可,同时,可以为子程序创建一个Handler对象,主线程可以通过该Handler对象像子程序传递用户的按键消息。

总结:

Surfaceandroid的一个重要元素,用于android画面的图形绘制。

SurfaceView是视图(View)的一个继承类,每一个SurfaceView都内嵌封装一个Surface。通过调用SurfaceHolder可以调用SurfaceView,控制图形的尺寸和大小。

SurfaceHolder 是通过getholder()来取得。

l  创立SurfaceHolder 对象后,用SurfaceHolder.Callback()来回调SurfaceHolder,对SurfaceView进行控制。

1.2              多线程

Android 的多线程是基于Linux本身的多线程机制,而多线程机制之间的同步又是通过java本身的线程同步,线程是运行在同一地址空间的不同调度单元,有自己的堆栈空间,而进程是运行在独立的,彼此之间互不察觉的不同调度单元。

 一个应用程序可能包含多个线程,每个线程都有一个run()方法,run()执行完毕后,所有的线程就自动结束。

  每个线程都有一个消息队列,用于不同线程之间传递消息。在run()方法内部,如果不主动读取消息队列中的消息,这些消息就是一些不用的消息,因为没被处理。

android系统中,读取消息和处理消息是两个步骤,并有不同的部分完成,先读取消息,然后才处理消息,但是,无论是本线程还是其他线程,都不能直接处理消息队列中的消息,需要通过线程内部定义一个Handler类对象来处理消息队列,一个Thread只能有一个Handler对象,在实际应用中,读取消息队列一般需要循环执行,即不断的从消息队列中获取消息并进行相应的处理,这就需要一个Looper对象。

Looper对象用于循环读取消息队列的值,并回调Handler对象中定义的消息处理函数,同时,Looper对象还可以将读出的消息从队列中移除,执行完一次消息处理后,在循环从消息队列中读取下一个消息,知道Looper对象调用stop方法退出循环,若没有消息,Looper对象则会等待,线程不会退出。

为了方便使用Looper功能,android又定义了一个HandlerThread类,该类基于Thread,并且内部已经添加了Looper功能,只需复写其onLooperPrepared()方法,android中,一个Activity就是一个线程,多个Activity之间的切换是在同一个线程中。

1.2.1      Thread

Thread 是一个类,和java中的基本相同,但是抛弃了一些java线程不安全的做法,比如,终止一个thread,在java中,可以使用threadStop等,但在android中,这些方法没有实现,不能直接使用。

新建一个thread需要两个函数:

1、          构造函数

  android中,新建的线程多为activityservice等程序片段服务,而在线程的内部执行过程中,很多时候都需要使用应用程序内部的context对象,因此,构造函数中往往会传递应用程序的context对象,从而在线程的内部可以调用context相关的系统服务。

2、          Run()函数

 该函数是thread中必须使用的对象,用于完成具体的任务。启动线程时,不能直接调用thread.run()方法,而是调用thread.start()方法启动,start()方法是thread内部使用的,该方法包括初始化线程的工作,然后回调run()方法,这些对应用程序是不可见的。

Run()方法执行完后就自动停止线程,因此,如果需要线程循环执行run方法,可以在run内部定义一个状态变量,通过检查该变量,决定是否执行,同时可在线程外设置该状态变量的值,从而终止该线程。

package com.java.lyn;

 

import java.io.IOException;

 

import android.graphics.Canvas;

import android.view.SurfaceHolder;

import static  com.java.lyn.Constant.*;

public class MenuThread extends Thread{

     MenuView mv;

     SurfaceHolder holder;//显示一个surface的抽象接口,可以控制surface的大小和格式,

                           //以及在surface上编辑像素,和监视surace的改变。这个接口通//常通过SurfaceView类实现。

    public MenuThread(MenuView mv)//构造器

    {

        this.mv = mv;

        this.holder =mv.getHolder();

    }

    public void run()//run()方法

    {

        Canvas canvas;

        while(MENU_FLAG)

        {

            canvas = null;

            if(true)

            {

              try

              {

             canvas=this.holder.lockCanvas();//得到一个canvas实例

             synchronized(this.holder)

             {

                 mv.onDraw(canvas);

             }

              }catch(Exception e)

              {

              e.printStackTrace();

              }

              finally

              {

              if(canvas!=null)

              {

                   this.holder.unlockCanvasAndPost(canvas); // 将画好的画布提交 

              }

                   

              }

           }

            try

            {

                sleep(2000);

            }catch(Exception e)

              {

              e.printStackTrace();

              }

         }

    }

}

1.2.2      Runnable

  作用和thread相同,只是这是一个接口,待看。。。。。。。。

 

1.3              消息发送handler

Handler用于处理线程中的消息队列,当looper从消息队列中获取消息后,会把消息派发给handler对象。一个线程一个handler对象,所以,只要拥有其他线程的handler对象的引用,就可以像其发送消息,还可以给本线程发送消息。

一般有两种用途:

1、          实现一个定时任务。

2、          在线程间传递数据。

对于1.需要首先了解下message的结构,他是一个数据结构类,包含很多成员变量和方法,对于简单的消息处理,一般需要了解3项,分别是:

   In what:用于区分消息类型

   Int arg1:额外的消息参数

Int arg2:额外的消息参数;

(1)handler发送消息方式

两种:一类是postXXX()方法,

一类是sendXXX方法,该方法发送一个message类型的消息到消息队列,当消息被处理时,系统会调用handler对象定义的handlermessage方法处理该消息,实现定时任务时主要用到sendXXX()方法:

1sendEmptyMessage(int)空消息是指仅仅包含what值。

case MotionEvent.ACTION_UP:

            if(x>=0&&x<=105&&y>=300&&y<=335)

            {

                activity.hd.sendEmptyMessage(GAME_LOAD);

            }

            else if(x>=0&&x<=105&&y>=340&&y<=375)

            {

                activity.hd.sendEmptyMessage(GAME_HELP);

            }

            else if(x>=0&&x<=105&&y>=380&&y<=415)

            {

                activity.hd.sendEmptyMessage(GAME_ABOUT);

            }

            else if(x>=0&&x<=105&&y>=420&&y<=455)

            {

                System.exit(0);

            }

Exp2:

hd=new Handler()

        {   

        @Override

        public void handleMessage(Message msg)

        {

             super.handleMessage(msg);//

            switch(msg.what)

            {

            case GAME_SOUND:

             sv=new SoundView(PuzzlesgameActivity.this);

                    setContentView(sv);

                    break;

            case GAME_MENU:

             MENU_FLAG=true;//设置MenuThread标志位为true

             mv=new MenuView(PuzzlesgameActivity.this);

             setContentView(mv);

                    break;

             case GAME_LOAD:

             MENU_FLAG=false;//设置MenuThread标志位为false

             setContentView(R.layout.icon);

             new Thread()

             {

                 public void run()

                 {

                     try

                     {

                         sleep(2000);

                     }catch(Exception e)

                     {

                     e.printStackTrace();

                     }

                        hd.sendEmptyMessage(GAME_PLAY);

                 }

            

                }.start();

                break;

}//分号

(2)同步实现进程:

Synchornized(){

   If()

Tyr{

………………..

}catch()

{

}finially{}

例如:

public void run()

  {

       Canvas canvas;

       while(MENU_FLAG)

       {

             canvas = null;

             if(true)

             {

             try

             {

                canvas=this.holder.lockCanvas();//得到一个canvas实例

                synchronized(this.holder)

                {

                     mv.onDraw(canvas);

                }

             }catch(Exception e)

             {

                 e.printStackTrace();

             }

             finally

             {

                 if(canvas!=null)

                 {

                       this.holder.unlockCanvasAndPost(canvas); // 将画好的画布提交 

                 }

                       

             }

          }

             try

             {

                  sleep(2000);

             }catch(Exception e)

             {

                 e.printStackTrace();

             }

         }

  }

1.4              Activity

每个Activity里面都包含一个window,每个window里面包含一个ViewGroup,而每个ViewGroup可以包含更多的view或者viewgroup

LinearGroupRelativeLayout都是viewgroup的子类。整个视图成为一个布局,一个布局称为一个xml文件,布局文件描述了在一个window中显示的视图(view),比如一个按钮,一段文本框,一副图片或者一个viewgroup,一个viewgroup又可以包含其他的view

每个Activity对应的界面可以称为ContentView,一个Activity 只能拥有一个ContentView,一个ContentView一般对应一个Layout.xml文件,动态界面无非是再通过程序向ContentView添加或者删除一些view/viewgroup;

Android 提供了设置其内部ContentView的函数——setContentView(),第一个参数是viewgroup对象,该对象可以来自一个静态的Layout.xml资源文件,也可以用程序动态创建。

 

 每个应用程序都有一个context对象,context对象可以访问应用程序中各个服务系统和系统资源,比如,context.getResources()方法就可以返回该context对应的应用程序中的资源对象,并通过该对象访问具体的资源,如一个图标等,应用程序可以有多个activity,但是只有一个context对象。

 

 

 

 

1.5               

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
简易相机用以练习 private SurfaceView surface; private Button shutter,position,back;//快门 private SurfaceHolder holder; private Camera camera;//声明相机 private String filepath = "";//照片保存路径 private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);//没有标题 this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏 this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//拍照过程屏幕一直处于高亮 //设置手机屏幕朝向,一共有7种 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); //SCREEN_ORIENTATION_BEHIND: 继承Activity堆栈当前Activity下面的那个Activity的方向 //SCREEN_ORIENTATION_LANDSCAPE: 横屏(风景照) ,显示时宽度大于高度 //SCREEN_ORIENTATION_PORTRAIT: 竖屏 (肖像照) , 显示时高度大于宽度 //SCREEN_ORIENTATION_SENSOR 由重力感应器来决定屏幕的朝向,它取决于用户如何持有设备,当设备被旋转时方向会随之在横屏与竖屏之间变化 //SCREEN_ORIENTATION_NOSENSOR: 忽略物理感应器——即显示方向与物理感应器无关,不管用户如何旋转设备显示方向都不会随着改变("unspecified"设置除外) //SCREEN_ORIENTATION_UNSPECIFIED: 未指定,此为默认值,由Android系统自己选择适当的方向,选择策略视具体设备的配置情况而定,因此不同的设备会有不同的方向选择 //SCREEN_ORIENTATION_USER: 用户当前的首选方向 setContentView(R.layout.activity_main); back = (Button) findViewById(R.id.camera_back); position = (Button) findViewById(R.id.camera_position); surface = (SurfaceView) findViewById(R.id.camera_surface); shutter = (Button) findViewById(R.id.camera_shutter); holder = surface.getHolder();//获得句柄 holder.addCallback(this);//添加回调 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//surfaceview不维护自己的缓冲区,等待屏幕渲染引擎将内容推送到用户面前 //设置监听 back.setOnClickListener(listener); position.setOnClickListener(listener); shutter.setOnClickListener(listener);
好的,以下是我给出的 Android Http请求实验小结Android Http请求实验小结Android进行网络请求,可以使用HttpURLConnection或HttpClient等方式。其,HttpURLConnection是Android SDK提供的基于HTTP协议的网络请求API,HttpClient则是Apache提供的开源网络请求API,但在Android 6.0及以上版本已被标记为过时,推荐使用HttpURLConnection。 HttpURLConnection的使用步骤: 1.创建URL对象,指定请求的URL地址。 2.调用URL对象的openConnection()方法,获取HttpURLConnection对象。 3.设置HttpURLConnection的请求方法、连接超时时间、读取超时时间等属性。 4.如果需要向服务器发送参数,可以通过HttpURLConnection对象的输出流将参数写入请求体。 5.调用HttpURLConnection对象的connect()方法,建立与服务器的连接。 6.读取服务器返回的数据,可以通过HttpURLConnection对象的输入流获取服务器返回的数据。 7.关闭HttpURLConnection对象和输入流、输出流等资源。 HttpClient的使用步骤: 1.创建HttpClient对象。 2.创建HttpGet或HttpPost等请求对象,指定请求的URL地址和请求参数等信息。 3.执行请求,获取服务器返回的HttpResponse对象。 4.解析HttpResponse对象,获取服务器返回的数据。 5.关闭HttpClient对象和HttpResponse等资源。 需要注意的是,在Android 9.0及以上版本,默认禁止应用程序使用非加密的流量进行网络请求,需要在AndroidManifest.xml文件添加以下代码: ``` <application android:usesCleartextTraffic="true"> ... </application> ``` 以上是Android Http请求实验小结,希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值