Android的入门知识须知

本文全面解析了Android的基础知识点,涵盖定义、系统架构、四大组件、六大布局和五大数据存储方式等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这几天在忙着复习功课,看面试题,海投简历,结果所有简历都石沉大海,唉,心塞.......

把已整理的知识点先传了吧。囊括了android的定义、系统架构、四大组件、六大布局和五大数据存储,有点多,慢慢理解就好了’

Android是什么?

Android是Google开发的基于Linux平台的手机开源操作系统,它包括操作系统、用户界面和应用程序。android采用了WebKit浏览器引擎,具备触摸屏、高级图形显示和上网功能,用户能够在手机上查看电子邮件 、搜索网址和观看视频节目等。


Android系统架构

android系统架构分为四层,从底层依次为:Linux核心层、系统运行库层、应用程序框架层、应用程序层。


Android四大组件

此处多摘自shenggaofei的csdn博客http://blog.youkuaiyun.com/shenggaofei/article/details/52450668

Android四大组件分别为:activity、service、contentProvider、broadcastReceiver

1.activity

activity是android系统中的四大组件之一,是用来显示view的组件,可用于与用户交互。一个android应用通常是通过activity来启动和运行。

一个activity通常就是一个单独的窗口,activity之间通过Intent进行通信。

android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity

2.service

service用于在后台处理一些耗时的逻辑,或者执行某些需要长期运行的任务,必要的时候我们可以在程序退出的情况下,让service在后台继续保持运行状态。

一、启动service的方法有两种:

(1)started(启动):当应用程序组件(如Activity)调用startService()方法启动服务时,服务处于started状态

(2)bound(绑定):当应用程序组件调用bindService()方法绑定服务时,服务处于bound状态

二、两种方法的区别:

(1)startService()方法启动服务,是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用。当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调stopSelf()法停止,或者由其他组件调用stopService()方法停止。

(2)bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

三、开发人员需要在应用程序配置文件中声明全部的service,使用<service></service>标签

3.contentProvider

1android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据

2)只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。

3ContentProvider实现数据共享ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,

因为android没有提供所有应用共同访问的公共存储区。

4)开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。

5ContentProvider使用URI来唯一标识其数据集,这里的URIcontent://作为前缀,表示该数据由ContentProvider来管理。

4.broadCastReceiver

1)你的应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activityservice来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。

(2)广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest文件中进行静态注册。

3)动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。


5.四大组件总结:

(1)四大组件都需要注册才可以使用,每个ActivityserviceContent Provider都需要在AndroidManifest文件中进行配置。而broadcastReceiver广播接收者的注册分静态注册(在AndroidManifest文件中进行配置)通过代码动态创建并以调用Context.registerReceiver()的方式注册至系统。

(2)四大组件的激活:

内容提供者的激活:当接收到ContentResolver发出的请求后,内容提供者被激活。而其它三种组件activity、服务和广播接收器被一种叫做intent的异步消息所激活

(3)四大组件的关闭:

内容提供者仅在响应ContentResolver提出请求的时候激活。而一个广播接收器仅在响应广播信息的时候激活。所以,没有必要去显式的关闭这些组件。

Activity关闭:可以通过调用它的finish()方法来关闭一个activity

服务关闭:对于通过startService()方法启动的服务要调用Context.stopService()方法关闭服务,使用bindService()方法启动的服务要调用Contex.unbindService()方法关闭服务。


Android系统是一个多任务(Multi-Task)的操作系统,可以在用手机听音乐的同时,也执行其他多个程序。每多执行一个应用程序,就会多耗费一些系统内存,

当同时执行的程序过多,或是关闭的程序没有正确释放掉内存,系统就会觉得越来越慢,甚至不稳定。为了解决这个问题,Android引入了一个新的机制,即生命周期(Life Cycle)。

Android六大布局

LinearLayout(线性布局)、RelativeLayout(相对布局)、FramLayout(帧布局)、TableLayout(表格布局)、GridLayout(网格布局)、AbsoluteLayout(绝对布局)。


android中声明程序布局有两种方式:1) 使用XML文件描述界面布局;2) 在Java代码中通过调用方法进行控制。

使用XML文件声明有以下3个特点:

1) 将程序的表现层和控制层分离;

2) 在后期修改用户界面时,无须更改程序的源程序;

3) 可通过WYSIWYG可视化工具直接看到所设计的用户界面,有利于加快界面设计的过程。

建议尽量采用XML文件声明界面元素布局。在程序运行时动态添加界面布局会大大降低应用响应速度,但依然可以在必要时动态改变屏幕内容。


Android五大存储

SharedPreferences、文件存储、SQLite数据库方式、contentProvider(内容提供器)、网络。

1.SharedPreferences方式

Android提供用来存储一些简单的配置信息的一种机制,例如,一些默认欢迎语、登录的用户名和密码等。其以键值对的方式存储,

使得我们可以很方便的读取和存入。也常常用于存储用户的偏好设置。

 1)程序要实现的功能:

我们在Name文本框中输入wangwu,在Password文本框中输入123456,然后退出这个应用。我们在应用程序列表中找到这个应用,

重新启动,可以看到其使用了前面输入的Name和Password,也就是我们常常遇到的记录用户输入的账号和密码。

2)实现的代码

很简单的布局,此处省略代码,直接上java代码实现存储账号密码等。

    public static final String SETTING_INFOS = "SETTING_Infos";   
    public static final String NAME = "NAME";   
    public static final String PASSWORD = "PASSWORD";   
    private EditText field_name;  //接收用户名的组件  
    private EditText filed_pass;  //接收密码的组件  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        //Find VIew   
        field_name = (EditText) findViewById(R.id.name);  //首先获取用来输入用户名的组件  
        filed_pass = (EditText) findViewById(R.id.password); //同时也需要获取输入密码的组件  
  
        // Restore preferences  
        SharedPreferences settings = getSharedPreferences(SETTING_INFOS, 0); //获取一个SharedPreferences对象  
        String name = settings.getString(NAME, "");  //取出保存的NAME  
        String password = settings.getString(PASSWORD, ""); //取出保存的PASSWORD  
  
        //Set value  
        field_name.setText(name);  //将取出来的用户名赋予field_name  
        filed_pass.setText(password);  //将取出来的密码赋予filed_pass  
    }  
      
    @Override   
    protected void onStop(){   
        super.onStop();   
          
        SharedPreferences settings = getSharedPreferences(SETTING_INFOS, 0); //首先获取一个SharedPreferences对象  
        settings.edit()   
                .putString(NAME, field_name.getText().toString())   
                .putString(PASSWORD, filed_pass.getText().toString())   
                .commit();   
    } //将用户名和密码保存进去  

SharedPreferences是以XML的格式以文件的方式自动保存的,在DDMS中的File Explorer中展开到/data/data/<package name>/shared_prefs下,以上面这个为例,可以看到一个叫做SETTING_Infos.xml的文件。

SharedPrefreences对象与SQLite数据库相比,免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是它也有自身的缺陷,譬如其只能存储boolean,int,float,long和String五种简单的数据类型,无法进行条件查询等。所以不论它的数据存储操作是如何简单,也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式。

       注意:Preferences只能在同一个包内使用,不能在不同的包之间使用。


2.文件存储

context提供了两份方法来打开数据文件里的文件IO流,分别是FileInputStream.openFileInput(String name)和openFileOutput(String name,int mode)。

这两个方法第一个参数用于指定文件名,第二个参数指定打开文件的模式。打开文件模式有以下几种:

MODE_PRIVATE:默认的操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原有的内容。

MODE_APPEND:追加模式,此时会先检查文件是否存在,存在就往文件中追加,否则就创建新文件。

MODE_WORLD_READABLE:读取模式,表示当前文件可以被其他应用读取。

MODE_WORLD_WRITEABLE:写入模式,表示当前文件可以被其他应用写入。

除了这两个方法之外,Context还提供了如下几个重要的方法:

getDir(String name,int mode):在应用程序的数据文件夹下获取或者创建name对应的子目录。

File.getFilesDir():获取该应用程序的数据文件夹的绝对路径。

String[ ] fileList():返回该数据文件夹的全部文件。

下面给出一个实际的小案例:

布局界面就一个EditText和两个Button按钮,负责文件的读写功能。简单布局,代码依然省略了,只看核心代码。

/**文件的读取功能*/
public String read() {
    try {
            FileInputStream inStream = this.openFileInput("message.txt");
            byte[] buffer = new byte[1024];
            int hasRead = 0;
            StringBuilder sb = new StringBuilder();
            while ((hasRead = inStream.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, hasRead));
            }
       /**文件的IO流在使用结束后一定要关闭*/
            inStream.close();
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return null;
    }
/**文件的写入功能*/
public void write(String msg){
        // 步骤1:获取输入值
        if(msg == null) return;
        try {
            // 步骤2:创建一个FileOutputStream对象,MODE_APPEND追加模式
            FileOutputStream fos = openFileOutput("message.txt",
                    MODE_APPEND);
            // 步骤3:将获取过来的值放入文件
            fos.write(msg.getBytes());
            // 步骤4:关闭数据流
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
两个方法的第一参数用于指定文件名称,不能包含路径分隔符“/”。

要注意的一点就是,在读写的文件位于sdcard上时,就麻烦了很多。

首先要判断手机上是否存在sd卡,Environment.getExternalStorageState()方法进行判断。并且应用程序要具有读写SD卡的权限,如下:

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

案列如下:

// 文件写操作函数
    private void write(String content) {
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) { // 如果sdcard存在
            File file = new File(Environment.getExternalStorageDirectory()
                    .toString()+ File.separator+ DIR + File.separator
                    + FILENAME); // 定义File类对象
            if (!file.getParentFile().exists()) { // 父文件夹不存在
                file.getParentFile().mkdirs(); // 创建文件夹
            }
            PrintStream out = null; // 打印流对象用于输出
            try {
                out = new PrintStream(new FileOutputStream(file, true)); // 追加文件
                out.println(content);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    out.close(); // 关闭打印流
                }
            }
        } else { // SDCard不存在,使用Toast提示用户
            Toast.makeText(this, "保存失败,SD卡不存在!", Toast.LENGTH_LONG).show();
        }
    }

    // 文件读操作函数
    private String read() {

        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) { // 如果sdcard存在
            File file = new File(Environment.getExternalStorageDirectory()
                    .toString()
                    + File.separator
                    + DIR
                    + File.separator
                    + FILENAME); // 定义File类对象
            if (!file.getParentFile().exists()) { // 父文件夹不存在
                file.getParentFile().mkdirs(); // 创建文件夹
            }
            Scanner scan = null; // 扫描输入
            StringBuilder sb = new StringBuilder();
            try {
                scan = new Scanner(new FileInputStream(file)); // 实例化Scanner
                while (scan.hasNext()) { // 循环读取
                    sb.append(scan.next() + "\n"); // 设置文本
                }
                return sb.toString();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (scan != null) {
                    scan.close(); // 关闭打印流
                }
            }
        } else { // SDCard不存在,使用Toast提示用户
            Toast.makeText(this, "读取失败,SD卡不存在!", Toast.LENGTH_LONG).show();
        }
        return null;
    }

3.SQLite存储数据

SQLite是Google为Andorid提供的一款轻量级的关系型数据库系统,它支持SQL语言,在数据存储、管理、维护等各方面都相当出色,功能也非常的强大。

SQLite具备六大特点:

1.轻量级
使用 SQLite 只需要带一个动态库,就可以享受它的全部功能,而且那个动态库的尺寸想当小。
2.独立性
SQLite 数据库的核心引擎不需要依赖第三方软件,也不需要所谓的“安装”。
3.隔离性
SQLite 数据库中所有的信息(比如表、视图、触发器等)都包含在一个文件夹内,方便管理和维护。
4.跨平台
SQLite 目前支持大部分操作系统,不至电脑操作系统更在众多的手机系统也是能够运行,比如:Android。
5.多语言接口
SQLite 数据库支持多语言编程接口。
6.安全性

SQLite 数据库通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但只能有一个可以写入数据。

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么。例如:可以在Integer类型的字段中存放字符串,或者在Boolean类型的字段中存放浮点数,或者在String类型字段中存放日期型值。

SQLiteDatabase类为我们提供了很多方法,实现对数据库数据的添加、更新和删除。

//执行SQL语句
1 SQLiteDatabase.executeSQL(String sql);  
2 SQLiteDatabase.executeSQL(String sql, Object[] bindArgs);//sql语句中使用占位符,然后第二个参数是实际的参数集 

除了统一的形式外,他们还有各自的操作方法:

db.insert(String table, String nullColumnHack, ContentValues values);  
db.update(String table, Contentvalues values, String whereClause, String whereArgs);  
db.delete(String table, String whereClause, String whereArgs);
这三个方法的第一个参数表示要操作的表名;

insert方法中的第二个参数表示如果插入的数据每一列都为空的话,需要指定此行中某一列的名称,系统将此列设置为NULL,不至于出现错误,第三个参数是ContentValues类型的变量,是键值对组成的Map。Key代表列名,value代表该列要插入的值;

update方法的第二个参数跟insert方法很类似,只不过它是更新该字段key为最新的value值,第三个参数whereClause表示WHERE表达式,譬如“age>?and age<?”等,最后的whereArgs参数是占位符的实际参数值;

delete方法的参数跟update的三四参数一样。


数据的添加

1.使用insert方法

ContentValues cv = new ContentValues();//实例化一个ContentValues用来装载待插入的数据
cv.put("title","you are beautiful");//添加title
cv.put("weather","sun"); //添加weather
cv.put("context","xxxx"); //添加context
String publish = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
cv.put("publish ",publish); //添加publish
db.insert("diary",null,cv);//执行插入操作
String whereClause = "username=?";//删除的条件
String[] whereArgs = {"Jack Johnson"};//删除的条件参数
db.delete("user",whereClause,whereArgs);//执行删除


2.使用execSQL方式来实现
String sql = "insert into user(username,password) values ('Jack Johnson','iLovePopMuisc');//插入操作的SQL语句
db.execSQL(sql);//执行SQL语句


数据的删除
1.使用delete方法
String whereClause = "username=?";//删除的条件
String[] whereArgs = {"Jack Johnson"};//删除的条件参数
db.delete("user",whereClause,whereArgs);//执行删除

2.使用execSQL方式来实现

String sql = "delete from user where username='Jack Johnson'";//删除操作的SQL语句
db.execSQL(sql);//执行删除操作


数据的修改

1.使用update方法

ContentValues cv = new ContentValues();//实例化ContentValues
cv.put("password","iHatePopMusic");//添加要更改的字段及内容
String whereClause = "username=?";//修改条件
String[] whereArgs = {"Jack Johnson"};//修改条件的参数
db.update("user",cv,whereClause,whereArgs);//执行修改

2.使用execSQL方式的实现

String sql = "update user set password = 'iHatePopMusic' where username='Jack Johnson'";//修改的SQL语句
db.execSQL(sql);//执行修改

数据的查询

接来下说一下数据查询,相对于增删改要复杂些,我们经常面对各种各样的查询条件,系统提供了较丰富的查询形式。

db.rawQuery(String sql, String[] selectionArgs);  
db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy);  
db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit);  
db.query(String distinct, String table, String[] columns, String selection, String[] selectionArgs,
	 String groupBy, String having, String orderBy, String limit);  

上面几种都是常用的查询方法, 各个参数分别代表的是:
selectionArgs条件语句的参数数组,table表名称,colums要查询的列的名称集,selection代表WHERE之后的条件语句,可以使用占位符,groupBy指定分组的列名,having指定分组条件,配合groupBy使用,orderBy指定排序的列名,limit指定分页参数,distinct指定“true”或“false”表示要不要过滤重复值
查询方法会返回一个Cursor对象,代表数据集的游标,Cursor也提供了一系列的方法,如下:

c.move(int offset); //以当前位置为参考,移动到指定行  
c.moveToFirst();    //移动到第一行  
c.moveToLast();     //移动到最后一行  
c.moveToPosition(int position); //移动到指定行  
c.moveToPrevious(); //移动到前一行  
c.moveToNext();     //移动到下一行  
c.isFirst();        //是否指向第一条  
c.isLast();     //是否指向最后一条  
c.isBeforeFirst();  //是否指向第一条之前  
c.isAfterLast();    //是否指向最后一条之后  
c.isNull(int columnIndex);  //指定列是否为空(列基数为0)  
c.isClosed();       //游标是否已关闭  
c.getCount();       //总数据项数  
c.getPosition();    //返回当前游标所指向的行数  
c.getColumnIndex(String columnName);//返回某列名对应的列索引值  
c.getString(int columnIndex);   //返回当前行指定列的值 

下面是查询数据的一个简单的案例:

String[] params =  {12345,123456};
Cursor cursor = db.query("user",columns,"ID=?",params,null,null,null);//查询并获得游标
if(cursor.moveToFirst()){//判断游标是否为空
    for(int i=0;i<cursor.getCount();i++){
        cursor.move(i);//移动到指定记录
        String username = cursor.getString(cursor.getColumnIndex("username");
        String password = cursor.getString(cursor.getColumnIndex("password"));
    }
}

然后我们再通过rawQuery方法实现一下带参数的查询:

Cursor result=db.rawQuery("SELECT ID, name, inventory FROM mytable");
//Cursor c = db.rawQuery("s name, inventory FROM mytable where ID=?",new Stirng[]{"123456"});     
result.moveToFirst(); 
while (!result.isAfterLast()) { 
    int id=result.getInt(0); 
    String name=result.getString(1); 
    int inventory=result.getInt(2); 
    // do something useful with these 
    result.moveToNext(); 
 } 
 result.close();



注意:当我们完成了对数据库的操作后,记得调用SQLiteDatebase的close()方法释放数据库连接,否则容易出现SQLiteException

4.内容提供器(Content Provider)

Content Provider是android的四大组件之一,主要用于在不同的程序之间实现数据的共享,一个程序可以通过实现Content Provider的抽象借口将自己的数据暴露出去。外界的程序需要通过ContentResolver接口访问ContentProvider提供的数据。在Activity中通过getContentResolver()可以得到当前应用的ContentResolver对象。Android提供了一些已经在系统中实现的标准的ContentProvider,譬如联系人信息,图片库等等,可以直接使用它访问设备上存储的联系人信息、图片等。ContentProvider和ContentResolver提供了一致的接口,供用户进行增删改查功能。如下:

query(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder);//通过Uri进行查询,返回一个Cursor。 
insert(Uri url, ContentValues values);//将一组数据插入到Uri 指定的地方。 
update(Uri uri, ContentValues values, String where, String[] selectionArgs);//更新Uri指定位置的数据。 
delete(Uri url, String where, String[] selectionArgs);//删除指定Uri并且符合一定条件的数据。

ContentProvider统一了数据的访问方式,使用的查询字符串有别于标准的SQL查询,它使用了特殊的Uri进行访问,Uri是由三部分组成“content://”+数据的路径+资源标识ID(可选),其中如果存在ID,就表示某一个具体的资源,否则就标识路径下的整体。
下面来进行一个案列的演示,首先是在一个程序中继承ContentProvider类,将共享的数据存储在ContentProvider中,核心代码如下:

//在Create中初始化一个数据库  
    @Override  
    public boolean onCreate() {  
        SQLiteDatabase db = this.getContext().openOrCreateDatabase("test_db.db3", Context.MODE_PRIVATE, null);  
        db.execSQL("create table tab(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");  
        ContentValues values = new ContentValues();  
        values.put("name", "test");  
        db.insert("tab", "_id", values);  
        db.close();  
        return true;  
    }  
  
    //实现query方法  
    @Override  
    public Cursor query(Uri uri, String[] projection, String selection,  
            String[] selectionArgs, String sortOrder) {  
        SQLiteDatabase db = this.getContext().openOrCreateDatabase("test_db.db3", Context.MODE_PRIVATE, null);  
        Cursor c = db.query("tab", null, null, null, null, null,null);  
        return c;  
    }
由于它是android的四大组件之一,需要在AndroidManifest.xml中声明,然后声明authorities属性定义此ContentProvider的Uri标识
<provider android:name=".MyProvider" android:authorities="com.test.MyProvider"/> 

然后在另一个应用程序中,通过ContentResolver获取第一个程序的ContentProvider中的数据:

@Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        //获取上下文  
        Context ctx = MainActivity.this;  
        //获取ContentResolver对象  
        ContentResolver resolver = ctx.getContentResolver();  
        //获取Uri对象  
        Uri uri = Uri.parse("content://com.test.MyProvider");  
        //获取数据  
        Cursor c = resolver.query(uri, null, null, null, null);  
       c.moveToFirst();  
       for(int i=0; i<c.getCount(); i++){  
            int index = c.getColumnIndexOrThrow("name");  
            String src = c.getString(index);  
            Log.d("", src);  
            c.moveToNext();  
       }  
    }  

5.网络存储方式

Android中的网络存储方式与android网络数据包息息相关,我们的android SDK是基于Java的,HttpUrlConnection是Java.NET包中提供的API,是我们访问网络的最原始最基本的API。我们一般使用HttpUrlConnection需要几个步骤:
1.将访问的路径字符串转换成URL:

URL url=new URL(path);

2.通过URL获取连接:

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

3.设置请求方式:(http的网络请求方式下面再介绍)

conn.setRequestMethod(GET);


4.设置连接超时 

conn.setConnectTimeout(5000);


5.设置请求头

conn.setRequestProperty(User-Agent, Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0));


6.针对不同的响应码,做不同的操作(响应码200,表明相应成功,获取返回内容的输入流)
提供一个封装好的工具类:
public class MyStreamUtils {
    /**
     * 将输入流转换成字符串
     * 
     * @param is
     *            从网络获取的输入流
     * @return
     */
    public static String streamToString(InputStream is) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = is.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            baos.close();
            is.close();
            byte[] byteArray = baos.toByteArray();
            return new String(byteArray);
        } catch (Exception e) {
            Log.e(tag, e.toString());
            return null;
        }
    }
}

在HttpUrlConnection中有两种常用的请求方式,分别是GET和POST。它的默认是GET方式。
GET方式是从指定的服务器中获取数据,它的请求能够被缓存,所以即使点击了后退按钮或者是刷新按钮,都不会有太大的影响。GET请求会保留在浏览器历史记录中,也可被收藏为书签,但不应在处理敏感数据时使用,而且请求有长度限制。
POST方式是向指定的资源提交要被处理的数据,它跟GET是相反的。POST请求不会被缓存,所以如果点击了后退或者是刷新按钮,数据会被重新提交。POST请求不会保留在浏览器历史记录中,不能被收藏为书签,POST请求对数据长度没有要求。

首先是HttpUrlConnection发送GET请求:

public static String loginByGet(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username= + username + &password= + password;
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod(GET);
            int code = conn.getResponseCode();
            if (code == 200) {
                InputStream is = conn.getInputStream(); 
                return MyStreamUtils.streamToString(is);// 字节流转换成字符串

            } else {
                return 网络访问失败;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 网络访问失败;
        }
    }

HttpUrlConnection发送POST请求:

public static String loginByPost(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod(POST);
            conn.setRequestProperty(Content-Type, application/x-www-form-urlencoded);
            String data = username= + username + &password= + password;
            conn.setRequestProperty(Content-Length, data.length() + );
            // POST方式,其实就是浏览器把数据写给服务器
            conn.setDoOutput(true); // 设置可输出流
            OutputStream os = conn.getOutputStream(); // 获取输出流
            os.write(data.getBytes()); // 将数据写给服务器
            int code = conn.getResponseCode();
            if (code == 200) {
                InputStream is = conn.getInputStream();
                return MyStreamUtils.streamToString(is);
            } else {
                return 网络访问失败;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 网络访问失败;
        }
    }


HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。,值得注意的是在android2.2之后Android官方就已经宣布不建议使用HttpClient了。
由于HttpClient的API数量过多,使得我们很难在不破坏兼容性的情况下对它进行升级和扩展,所以目前Android团队在提升和优化HttpClient方面的工作态度并不积极。然后我就也偷懒了,对httpClient没怎么关注,只是知道有这么个请求就是了。。。。。

至此,关于Android的一些基础知识整理完毕了,后续就是要多跟那些大大们学习第三方框架了,还有源码的解读以及android的性能优化,任重而道远,皮皮虾,我们走。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值