详细讲解Android的网络通信(HttpUrlConnection和HttpClient)

前言,Android的网络通信的方式有两种:使用Socket或者HTTP,今天这一篇我们详细讲解使用HTTP实现的网络通信,HTTP又包括两种方式编程方式:

(1)HttpUrlConnection;

(2)HttpClient;

   好了,我们直接进行讲解,当然之前也会有一部分有关Android网络通信的其他知识,我们也应该了解。

 

一.获取网络状态的方法

(1)MainActivity.java中的关键代码

1
2
3
4
5
6
7
8
//网络管理类,可以判断是否能上网,以及网络类型
            ConnectivityManager cm=(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo info=cm.getActiveNetworkInfo();
            if(info!=null){
                Toast.makeText(MainActivity.this"连网正常"+info.getTypeName(), Toast.LENGTH_SHORT).show();
            }else{
                Toast.makeText(MainActivity.this"未连网", Toast.LENGTH_SHORT).show();
            }

(2)注意:一定要在主配置文件中增加这个权限

   它是application的兄弟标签:

1<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

(3)OK,我们看一下我们的设备的上网状态和类型吧:

 

二.使用URL访问网页源码

(1)MainActivity.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.example.l0903_urldata;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
/**
 * 访问网页源码
 * @author asus
 *
 */
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            //访问百度的html文件的源码
            InputStream is=new URL("http://www.baidu.com").openStream();
            //读取数据的包装流
            BufferedReader br=new BufferedReader(new InputStreamReader(is));
            //str用于读取一行数据
            String str=null;
            //StringBuffer用于存储所欲数据
            StringBuffer sb=new StringBuffer();
            while((str=br.readLine())!=null){
                sb.append(str);
            }
            System.out.println(sb.toString());
        catch (MalformedURLException e) {
            e.printStackTrace();
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

(2)注意:有关网络的操作都需要在主配置文件里添加下面这个权限:

1<uses-permission android:name="android.permission.INTERNET"/>

 

三.WebView 控件的简单使用

   

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.example.l0903_webview;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
/**
 * 就是一个浏览器控件
 * 其实没什么用
 * @author asus
 *
 */
public class MainActivity extends Activity {
    private WebView wv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        wv=(WebView) findViewById(R.id.webView1);
        //WebView控件的方法,loadUrl用于加载指定的网络地址
        wv.loadUrl("http://www.baidu.com");
    }
}

   运行效果:

 

四.使用HttpUrlConnection的编写方式实现Android的网络通信

1.首先,自己先搭建一个服务器:

 

 

2.下面是客户端的事了:

(1)通过get方式:

   MainActivity.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.example.l0903_httpurlcnectionget;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
/**
 * 通过Get方法获取服务器的数据
 * 直接在地址中用"?+键值+value"的方式来使用
 * 所以传递的参数直接显示出来,不安全
 * @author asus
 *
 */
public class MainActivity extends Activity {
    private HttpURLConnection conn;
    private URL url;
    private InputStream is;
    private TextView tv;
    private EditText et;
    private String name;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv=(TextView) findViewById(R.id.textView1);
        et=(EditText) findViewById(R.id.editText1);
        findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
                                                                                                                                              
            @Override
            public void onClick(View v) {
                name=et.getText().toString();
                //定义访问的服务器地址,10.0.2.2是Android的访问的本地服务器地址
                String urlDate="http://10.0.2.2:8080/My_Service/webdate.jsp?name="+name;
                try {
                    //封装访问服务器的地址
                    url=new URL(urlDate);
                    try {
                        //打开对服务器的连接
                        conn=(HttpURLConnection) url.openConnection();
                        //连接服务器
                        conn.connect();
                        /**读入服务器数据的过程**/
                        //得到输入流
                        is=conn.getInputStream();
                        //创建包装流
                        BufferedReader br=new BufferedReader(new InputStreamReader(is));
                        //定义String类型用于储存单行数据
                        String line=null;
                        //创建StringBuffer对象用于存储所有数据
                        StringBuffer sb=new StringBuffer();
                        while((line=br.readLine())!=null){
                            sb.append(line);
                        }
                        //用TextView显示接收的服务器数据
                        tv.setText(sb.toString());
                        System.out.println(sb.toString());
                    catch (IOException e) {
                        e.printStackTrace();
                    }
                catch (MalformedURLException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

   权限(同上面第二个,所有与网络有关的操作都需要添加,下面的就不再赘述了)

   运行效果:

 

(2)通过post方式(安全)

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.example.l0903_httpurlconectionpost;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
/**
 * 通过Post方法传递参数
 * 安全
 * @author asus
 *
 */
public class MainActivity extends Activity {
    private HttpURLConnection conn;
    private URL url;
    private InputStream is;
    private OutputStream os;
    private EditText et;
    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et=(EditText) findViewById(R.id.editText1);
        tv=(TextView) findViewById(R.id.tv);
        findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
                                                                                   
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                String urlDate="http://10.0.2.2:8080/My_Service/webdate.jsp";
                try {
                    url=new URL(urlDate);
                    try {
                        //打开服务器
                        conn=(HttpURLConnection) url.openConnection();
                        //设置输入输出流
                        conn.setDoOutput(true);
                        conn.setDoInput(true);
                        //设置请求的方法为Post
                        conn.setRequestMethod("POST");
                        //Post方式不能缓存数据,则需要手动设置使用缓存的值为false
                        conn.setUseCaches(false);
                        //连接数据库
                        conn.connect();
                        /**写入参数**/
                        os=conn.getOutputStream();
                        //封装写给服务器的数据(这里是要传递的参数)
                        DataOutputStream dos=new DataOutputStream(os);
                        //写方法:name是key值不能变,编码方式使用UTF-8可以用中文
                        dos.writeBytes("name="+URLEncoder.encode(et.getText().toString(), "UTF-8"));
                        //关闭外包装流
                        dos.close();
                        /**读服务器数据**/
                        is=conn.getInputStream();
                        BufferedReader br=new BufferedReader(new InputStreamReader(is));
                        String line=null;
                        StringBuffer sb=new StringBuffer();
                        while((line=br.readLine())!=null){
                            sb.append(line);
                        }
                        tv.setText(sb.toString());
                        System.out.println(sb.toString());
                    catch (IOException e) {
                        e.printStackTrace();
                    }
                catch (MalformedURLException e) {
                    e.printStackTrace();
                }
            }
        });
                                                                           
    }
}

 

 

五.使用HttpClient的编写方式实现Android的网络通信

1.服务器同上;

2.使用get的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.example.l0903_http_get;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
    private HttpGet get;
    private HttpClient cliet;
    private HttpResponse response;
    private HttpEntity entity;
    private InputStream is;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        get=new HttpGet("http://10.0.2.2:8080/My_Service/webdate.jsp?name=ooooooo");
        cliet=new DefaultHttpClient();
        try {
            response=cliet.execute(get);
            entity=response.getEntity();
            is=entity.getContent();
            BufferedReader br=new BufferedReader(new InputStreamReader(is));
            String line=null;
            StringBuffer sb=new StringBuffer();
            while((line=br.readLine())!=null){
                sb.append(line);
            }
            System.out.println(sb.toString());
        catch (ClientProtocolException e) {
            e.printStackTrace();
        catch (IOException e) {
            e.printStackTrace();
        }
                                                
    }
}

 

3.使用post的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package com.example.l0903_http_post;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
    //创建请求对象
    private HttpPost post;
    //创建客户端对象
    private HttpClient cliet;
    //创建发送请求的对象
    private HttpResponse response;
    //
    private UrlEncodedFormEntity urlEntity;
    //创建接收返回数据的对象
    private HttpEntity entity;
    //创建流对象
    private InputStream is;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //包装请求的地址
        post=new HttpPost("http://10.0.2.2:8080/My_Service/webdate.jsp");
        //创建默认的客户端对象
        cliet=new DefaultHttpClient();
        //用list封装要向服务器端发送的参数
        List<BasicNameValuePair> pairs=new ArrayList<BasicNameValuePair>();
        pairs.add(new BasicNameValuePair("name""llllllllll"));
        try {
            //用UrlEncodedFormEntity来封装List对象
            urlEntity=new UrlEncodedFormEntity(pairs);
            //设置使用的Entity
            post.setEntity(urlEntity);
            try {
                //客户端开始向指定的网址发送请求
                response=cliet.execute(post);
                //获得请求的Entity
                entity=response.getEntity();
                is=entity.getContent();
                //下面是读取数据的过程
                BufferedReader br=new BufferedReader(new InputStreamReader(is));
                String line=null;
                StringBuffer sb=new StringBuffer();
                while((line=br.readLine())!=null){
                    sb.append(line);
                }
                System.out.println(sb.toString());
            catch (ClientProtocolException e) {
                e.printStackTrace();
            catch (IOException e) {
                e.printStackTrace();
            }
        catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
                                             
                                             
    }
}

 

4.实现HttpClient通信与AsyncTask异步机制的结合:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package com.example.l0903_http_asynctask_get;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;
/**
 *
 * @author asus
 *
 */
public class MainActivity extends Activity {
    private TextView tv;// 创建请求对象
    private HttpGet httpGet;
    // 创建客户端对象
    private HttpClient httpClient;
    // 发送请求的对象
    private HttpResponse httpResponse;
    // 接收返回数据
    private HttpEntity httpEntity;
    // 创建流
    private InputStream in;
    private ProgressDialog pd;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        AsyncTask<String, Void, String> asyncTask = new AsyncTask<String, Void, String>() {
            @Override
            protected String doInString...  params) {
                String urlstr = params[0];
                httpGet = new HttpGet(urlstr);
                httpClient = new DefaultHttpClient();
                try {
                    // 向服务器端发送请求
                    httpResponse = httpClient.execute(httpGet);
                    httpEntity = httpResponse.getEntity();
                    in = httpEntity.getContent();
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(in));
                    String line = null;
                    StringBuffer sb = new StringBuffer();
                    while ((line = br.readLine()) != null) {
                        sb.append(line);
                    }
                    System.out.println(sb.toString());
                    return sb.toString();
                catch (ClientProtocolException e) {
                    e.printStackTrace();
                catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
            @Override
            protected void onPostExecute(String result) {
                if (result != null) {
                    tv.setText(result);
                    pd.dismiss();// 消除dialog
                }
                super.onPostExecute(result);
            }
        };
        pd = ProgressDialog.show(this"请稍后。。。""正在请求数据");
        asyncTask.execute("http://10.0.2.2:8080/My_Service/webdate.jsp?name=haha&age=hh");
    }
}

运行效果:

 

转载于:https://www.cnblogs.com/AceIsSunshineRain/p/5095137.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/272506.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常见通信协议HTTP、TCP、UDP的简单介绍

TCP HTTP UDP:都是通信协议&#xff0c;也就是通信时所遵守的规则&#xff0c;只有双方按照这个规则“说话”&#xff0c;对方才能理解或为之服务。TCP HTTP UDP三者的关系:TCP/IP是个协议组&#xff0c;可分为四个层次&#xff1a;网络接口层、网络层、传输层和应用层…

创建进程相关函数

fork函数 pid_t fork(void); fork函数调用成功&#xff0c; 返回两次 在fork函数执行完毕后 如果创建新进程成功&#xff0c;则出现两个进程 一个是子进程&#xff0c;一个是父进程 在子进程中&#xff0c;fork函数返回0 在父进程中&#xff0c;fork返回新创建子进程的进程ID…

实现Windows和Linux之间的文件共享

一、windows 向linux共享文件(这里都是以win10和ubuntu为例)首先&#xff0c;打开网络共享中心。如图1图1打开更改高级共享设置&#xff08;图2&#xff09;图 2选择启用网络发现以及启用文件和打印机共享&#xff0c;然后点击保存更改。接着&#xff0c;选择你要共享的文件夹&…

鸡啄米MFC教程笔记之七:对话框:为控件添加消息处理函数

MFC为对话框和控件等定义了诸多消息&#xff0c;我们对它们操作时会触发消息&#xff0c;这些消息最终由消息处理函数处理。比如我们点击按钮时就会产生BN_CLICKED消息&#xff0c;修改编辑框内容时会产生EN_CHANGE消息等。一般为了让某种操作达到效果&#xff0c;我们只需要实…

进程的退出方式以及僵尸进程和孤儿进程

&#xff08;1&#xff09;正常退出 &#xff08;2&#xff09;异常退出 检查wait和waitpid所返回的终止状态的宏 宏说明WIFEXITED(status)若为正常终止子进程返回的状态&#xff0c;则为真。对于这种情况可执行WEXITSTATUS(status)&#xff0c;取子进程传送给exit、_exit或_…

java中的动态代理----自己手动实现

代码使用了common-io&#xff0c;需要其jar 1 接口 Java代码 public interface Pruduct { void selling(); } 2 书籍类 Java代码 public class Book implements Pruduct { Override public void selling() { try { Thread.sleep(1000…

Code Project精彩系列(1)

ApplicationsCrafting a C# forms Editor From scratchhttp://www.codeproject.com/csharp/SharpFormEditorDemo.asp建立一个类似C#的环境, 实现控件拖拉&#xff0c;属性Packet Capture and Analayzer网络封包截获http://www.codeproject.com/csharp/pacanal.aspA tool to cha…

Code Project精彩系列(2)

Windows FormsFireball Resourcer把各种资源嵌入应用程序资源Window Hiding with C#隐藏窗体, 似乎是其它运行的窗体 JProper Threading in Winforms .NETWindows Forms User Settings in C#使用VS设置设定forms, coolA Pretty Good Splash Screen in C#一个自绘可爱屏幕A curt…

python bool值要注意的一些地方

1、像(),[],{}这三个是可以通过bool(()),bool([]),bool({})转化为bool值的&#xff1b;且它们转化后的结果为False。但是这三个值它本身并不等于False、切记不可以与False 直接进行比较。 #!/usr/bin/python #!coding:utf-8 import sysif __name__ "__main__":falseL…

前端必备知识点—SVG

基本内容什么是SVG? 全称为Scalable Vector Graphics&#xff0c;是一种使用XML技术描述二维图形的语言&#xff0c;简单来说 - 矢量图(不失真)SVG与HTML5的关系早在HTML5之前,存在SVG技术SVG文件扩展名为".svg"在HTML5出现之前,要在HTML页面中引入SVG文件在HTML5出…

CocoaPods安装和使用及问题:Setting up CocoaPods master repo

CocoaPods是什么&#xff1f; 当你开发iOS应用时&#xff0c;会经常使用到很多第三方开源类库&#xff0c;比如JSONKit&#xff0c;AFNetWorking等等。可能某个类库又用到其他类库&#xff0c;所以要使用它&#xff0c;必须得另外下载其他类库&#xff0c;而其他类库又用到其他…

进程间的通信IPC(无名管道和命名管道)

进程间的通信IPC介绍 进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09;是指在不同进程之间传播或交换信息。 IPC的方式通常有管道&#xff08;包括无名管道和命名管道&#xff09;、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket…

那些关于浏览器的趣图和幽默段子

1、当浏览器化作一种枪&#xff0c;你喜欢用哪种呢&#xff1f;2、这神奇的反射弧&#xff0c;有点长…3、浏览器们成长的烦恼4、这么说来&#xff0c;IE浏览器扳回一分&#xff01;5、如何用浏览器区分 HTML和 HTML56、都在吹牛&#xff0c;还是IE最务实&#xff01;7、主流浏…

前端新手程序员不知道的 20个小技巧

1.作为前端开发者&#xff0c;使用双显示器能大幅提高开发效率。2.学编程最好的语言不是PHP&#xff0c;是English。3.东西交付之前偷偷测试一遍。4.问别人之前最好先自己百度&#xff0c;google一下&#xff0c;以免问出太低级的问题。5.把觉得不靠谱的需求放到最后做&#xf…

DBA十大必备工具(SQLServer)

曾经和一些DBA和数据库开发人员交流时&#xff0c;问他们都用过一些什么样的DB方面的工具&#xff0c;大部分人除了SSMS和Profile之外&#xff0c;基本就没有使用过其他工具了&#xff1b;诚然&#xff0c;SSMS和Profile足够强大&#xff0c;工作的大部分内容都能通过它们搞定&…

JS一些常用的类库

一、返回上一页&#xff08;history&#xff09;发觉有两种用法&#xff1a;1、javascript:history.back(-1);2、javascript:history.go(-1);它们俩的区别是&#xff1a;history.back(-1):直接返回当前页的上一页&#xff0c;数据全部消息&#xff0c;返回新页面history.go(-1)…

Linux上线程开发API概要(线程)

进程与线程 典型的UNIX/Linux进程可以看成只有一个控制线程&#xff1a;一个进程在同一时刻只做一件事情。有了多个控制线程后&#xff0c;在程序设计时可以把进程设计成在同一时刻做不止一件事&#xff0c;每个线程各自处理独立的任务。 进程是程序执行时的一个实例&…

Redis学习笔记1-Redis数据类型

Redis数据类型 Redis支持5种数据类型&#xff0c;它们描述如下&#xff1a; Strings - 字符串 字符串是 Redis 最基本的数据类型。Redis 字符串是二进制安全的&#xff0c;也就是说&#xff0c;一个 Redis 字符串可以包含任意类型的数据&#xff0c;一个字符串最大为 512M 字节…

30个非常有趣的404错误页面设计欣赏

当用户访问一个不存在的页面的时候就会出现404错误页面&#xff0c;这对用户来说是很不友好的。所以很多网站都会去设计一个新颖的错误页面&#xff0c;以吸引用户继续浏览其它的网页内容。今天这篇文章就收集了30个非常有趣的404错误页面设计欣赏&#xff0c;希望能带给你灵感…

5 个最佳的 Linux 桌面环境

打算把每个桌面都试用一遍&#xff0c;但是那很费时间&#xff0c;而且确实有很多桌面环境可供选择&#xff0c;这就是我发表“最优秀的 Linux 桌面以及他们的优缺点”的目的&#xff0c;本文告诉你在选择桌面时需要注意些什么&#xff0c;让我们开始吧。1. KDE我想从第五个说起…