Android之Socket通信、List加载更多、Spinner下拉列表

时间:2022-09-18 19:55:52

  Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信。两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求。 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信。通过建立socket连接,可为通信双方的数据传输传提供通道。socket的主要特点有数据丢失率低,使用简单且易于移植。

1.1什么是Socket
  是一种抽象层,应用程序通过它来发送和接收数据,使用Socket可以将应用程序添加到网络中,与处于同一网络中的其他应用程序进行通信。简单来说,Socket提供了程序内部与外界通信的端口并为通信双方的提供了数据传输通道。

1.2Socket的分类
  根据不同的的底层协议,Socket的实现是多样化的。本指南中只介绍TCP/IP协议族的内容,在这个协议族当中主要的Socket类型为流套接字(streamsocket)和数据报套接字(datagramsocket)。流套接字将TCP作为其端对端协议,提供了一个可信赖的字节流服务。数据报套接字使用UDP协议,提供数据打包发送服务。 下面,我们来认识一下这两种Socket类型的基本实现模型。

1.3Socket简单例子:

  服务器端Socket服务代码:

public class MyServer {

    public static void main(String[] args) throws Exception{
ServerSocket ss = new ServerSocket(555);
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
String str = dis.readUTF();
System.out.print("客户端已连接");
dos.writeUTF("Server:"+str);
dos.flush();
dis.close();
s.close();
ss.close();
} }

  Android客户端的代码:

public class MainActivity extends Activity {
public static Button mybutton = null;//发送Socket请求
public static TextView mytext = null;//显示服务器返回的值
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mybutton = (Button)findViewById(R.id.button);
mytext = (TextView)findViewById(R.id.text);
mybutton.setOnClickListener(new mybuttonlistener()); } //按钮的点击事件
class mybuttonlistener implements OnClickListener{ PrintStream out = null;
BufferedReader buf = null;
Socket s = null; public void onClick(View v) {
try { s = new Socket("10.20.90.3", 555);//创建一个IP地址为:10.20.90.3,端口号为:555的Socket对象 DataOutputStream dos = new DataOutputStream(s.getOutputStream());//获得一个输出流
DataInputStream dis = new DataInputStream(s.getInputStream());//获得一个输入流
dos.writeUTF("河南理工大学ACM协会");//发送到服务器的请求值
String str = dis.readUTF();//获取服务器返回的参数
mytext.setText(str);
dos.flush();
dos.close();
dis.close();
s.close(); } catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} } }

  最简单的一个服务器<--->客户端Socket事例就实现了,客户端程序执行前,需要首先启动服务器端程序,当服务器端启动完成后,我们就可以通过Android客户端发送Socket请求了。这个事例中,我们向服务器端发送:“河南理工大学ACM协会”字段,服务器为我们返回:“Server:河南理工大学ACM协会”。代码很简单,当然关于Socket的知识绝对不仅仅包含这些,剩下的就看小伙伴们是不是感兴趣了。


  对于List的上滑加载更多,网络上有很多开源控件,本篇接下来我将带领大家一起学习一下,如何实现List的上滑加载更多。

  首先是我们的主Activity的布局文件,布局文件没有其它内容只有一个ListView控件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" > <ListView
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone">
</ListView> </RelativeLayout>

  我们的主Activity代码:

public class MainActivity extends Activity {

    private ListView listview ;//list容器
private List<String> data = new ArrayList<String>();//暂存数据的容器
private ArrayAdapter<String> adapter;
private final int number = 30;//每页的数据量
private final int maxpage = 5;//数据的页数
private int ItemCount;//显示的记录数
private int nextpage;
private boolean flag = true; //表示加载数据是否完成
private View tipView;//页脚view @SuppressLint("InflateParams")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_main); listview = (ListView)findViewById(R.id.listview);
listview.setOnScrollListener(new scrollListener());//滑动事件监听
listview.setOnItemClickListener(new onItemClickListener());//点击事件监听
tipView = getLayoutInflater().inflate(R.layout.listview_tip, null);//获得加载更多的页脚 /*
* 第一次加载
*/
data.addAll(new DataScroll().getDate(0, 30));//获得第一页需要显示的数据
adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.listview_item, R.id.textview, data);//将数据与对应的数据显示页面配对 /*
* 添加页脚必须依据下面的格式
*/
listview.addFooterView(tipView);//添加页脚(在加载数据之前)
listview.setAdapter(adapter);//必须在此句之前加载页脚
listview.removeFooterView(tipView);//删除页脚显示
} public final class scrollListener implements OnScrollListener{ @Override
public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) { int lastItemId = listview.getLastVisiblePosition();//获得屏幕Item的最后一条记录的ID
if((lastItemId+1)==totalItemCount){//判断是否已经拖动到页未
if(totalItemCount > 0){//判断是否加载的数据是最后一页数据
int currentpage = totalItemCount%number==0 ? totalItemCount/number : totalItemCount/number+1;
nextpage = currentpage + 1;
if(nextpage<=maxpage && flag){
flag = false;
ItemCount = totalItemCount;
listview.addFooterView(tipView);//显示加载更多页脚
new Thread(new Runnable() { @Override
public void run() {
//模拟网络加载数据
try {
Thread.sleep(3000);//模拟网络加载
} catch (InterruptedException e) {
e.printStackTrace();
}
DataScroll datascroll = new DataScroll();
List<String> result = datascroll.getDate(nextpage, number);
Hand.sendMessage(Hand.obtainMessage(100, result));
}
}).start();
}
}
} if(0==firstVisibleItem){
if(firstVisibleItem < 0){
Toast.makeText(MainActivity.this, "刷新", Toast.LENGTH_SHORT).show();
}
}
}
} //返回到主线程执行
Handler Hand = new Handler(){ @SuppressWarnings("unchecked")
@SuppressLint("HandlerLeak")
public void handleMessage(Message msg) {
data.addAll((List<String>) msg.obj);
adapter.notifyDataSetChanged();//告诉ListView数据已经发生改变,要求更新ListView界面
if(listview.getFooterViewsCount()>0){
listview.removeFooterView(tipView);
}
flag = true;
}
}; //List中各Item的点击事件
class onItemClickListener implements OnItemClickListener{ @Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(getApplicationContext(), position+" "+id, Toast.LENGTH_SHORT).show();
} } }

  接下来我们需要补充一下我们的Item的布局(listview_item.xml):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#aa00ff"
tools:context="${relativePackage}.${activityClass}" > <TextView
android:id="@+id/textview"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:textSize="18sp"
android:textColor="#aa0000"
android:singleLine="true"
/> </RelativeLayout>

  当然既然是加载更多,我们还需要一个提示用户正在加载更多的一个页脚(listview_tip.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" > <ProgressBar
android:id="@+id/progressBar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/textview" /> <TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:textColor="#000000"
android:singleLine="true"
android:text="数据加载中..." /> </LinearLayout>

  当然最重要的加载数据,这里我们因为为了简单起见,就没有通过网络加载更多数据,而是通过一个模拟加载函数类实现的一个模拟加载(DataScroll.java):

/*
* 模拟获得分页数据
*/
public class DataScroll {
public List<String> getDate(int nextpage, int maxResult){
int offset = 0;
if(nextpage!=0){
offset = (nextpage-2)*maxResult;
}
List<String > list = new ArrayList<String>();
for(int i=0; i<maxResult; i++){
list.add("List数据分批加载"+ ++offset);
}
return list;
}
}

  好了,我们的上滑加载更多的实现就为大家分享完毕,关于下滑刷新,小伙伴们可以通过监听用户滑动事件,来自行研究,很简单相信大家都能实现,有疑问欢迎留言讨论。


  Spinner:Android提供的下拉列表控件,接下来我将通过5个小例子,为大家介绍一下Spinner的系统自带样式与自定义样式,当然系统自带样式相对简单,我们就从简单开始入手,为大家一一介绍Spinner的使用。

  首先是布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<LinearLayout
android:id="@+id/linearone"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Spinner下拉列表"
android:textSize="25dip"
android:layout_gravity="center_horizontal"
/> <Spinner
android:id="@+id/spinner1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/arr"
android:spinnerMode="dropdown"
/> <Spinner
android:id="@+id/spinner2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/brr"
android:spinnerMode="dialog"
/> <Spinner
android:id="@+id/spinner3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Spinner
android:id="@+id/spinner4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:spinnerMode="dialog"
/>
<Spinner
android:id="@+id/spinner5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:spinnerMode="dialog"
/>
<Button
android:id="@+id/buttonone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="下一页"
/>
</LinearLayout>
</RelativeLayout>

  前两个控件使用的是Android自带Spinner下拉列表样式,红色部分是我在res->values->strings文件中设置的值:

<?xml version="1.0" encoding="utf-8"?>
<resources> <string name="app_name">下拉列表</string>
<string name="hello_world">Hello world!</string> <string-array name="arr"> <item>默认效果</item>
<item>河南</item>
<item>北京</item>
<item>上海</item> </string-array> <string-array name="brr"> <item>弹出效果</item>
<item>河南</item>
<item>北京</item>
<item>上海</item> </string-array> </resources>

  主Activity代码:

public class Activityone extends Activity {

    private Spinner spin1;//默认Spinner,在按钮下方显示
private Spinner spin2;//默认Spinner,通过Dialog的形式为用户展示
private Spinner spin3;//自定义Spinner,在按钮下方显示
private Spinner spin4;//自定义Spinner,通过Dialog的形式为用户展示
private Spinner spin5;//自定义Spinner,通过Dialog的形式为用户展示
private Button buttonone; private String [] array = new String [] {
"数组引用",
"代表",
"组长",
"小妹"
}; private String [] arrayadapt = new String [] {
"arrayadapt引用",
"代表",
"组长",
"小妹"
}; private List<String> list = new ArrayList<String>(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_one); list.add("list引用");
list.add("代表");
list.add("组长");
list.add("小妹"); buttonone=(Button)findViewById(R.id.buttonone);
spin1=(Spinner)findViewById(R.id.spinner1);
spin2=(Spinner)findViewById(R.id.spinner2);
spin3=(Spinner)findViewById(R.id.spinner3);
spin4=(Spinner)findViewById(R.id.spinner4);
spin5=(Spinner)findViewById(R.id.spinner5); ArrayAdapter<String> arrayadapter =
new ArrayAdapter<String>(Activityone.this, android.R.layout.simple_spinner_item, arrayadapt); spin5.setAdapter(arrayadapter); BaseAdapter baseadapterone = new baseadapterone();
spin3.setAdapter(baseadapterone); BaseAdapter baseadaptertwo = new baseadaptertwo();
spin4.setAdapter(baseadaptertwo);
//设置点击结果选择提示
spin4.setOnItemSelectedListener(new OnItemSelectedListener() { @Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(Activityone.this, list.get(position), Toast.LENGTH_SHORT).show();
} @Override
public void onNothingSelected(AdapterView<?> parent) { }
}); buttonone.setOnClickListener(new mybuttonistener()); } private class baseadapterone extends BaseAdapter{ @Override
public int getCount() {
return array.length;
} @Override
public Object getItem(int position) {
return null;
} @Override
public long getItemId(int position) {
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textview = new TextView(Activityone.this);
textview.setText(array[position]);
return textview;
} } private class baseadaptertwo extends BaseAdapter{ @Override
public int getCount() {
return list.size();
} @Override
public Object getItem(int position) {
return null;
} @Override
public long getItemId(int position) {
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textview = new TextView(Activityone.this);
textview.setText(list.get(position));
return textview;
} } class mybuttonistener implements OnClickListener{ @Override
public void onClick(View v) {
Intent intent = new Intent(Activityone.this,Activitytwo.class);
Activityone.this.startActivity(intent);
}
} }

  ok关于今天的内容介绍到此介绍,内容很简单,大家感兴趣的话可以实现一下。新手学习,高手交流。

Android之Socket通信、List加载更多、Spinner下拉列表的更多相关文章

  1. Android Demo 下拉刷新&plus;加载更多&plus;滑动删除

    小伙伴们在逛淘宝或者是各种app上,都可以看到这样的功能,下拉刷新和加载更多以及滑动删除,刷新,指刷洗之后使之变新,比喻突破旧的而创造出新的,比如在手机上浏览新闻的时候,使用下拉刷新的功能,我们可以第 ...

  2. Android ListView滑动底部自动加载更多

    直接上代码: // lv = (ListView) findViewById(R.id.lv); // // for(int i = 0;i < 50;i++){ // ls.add(&quot ...

  3. MVC中实现加载更多

    需要实现的功能: 数据太多想初次加载部分数据,在底部加上“加载更多”按钮 点击后加载第二页数据(从数据库只取指定页数据)后接在已有数据后面(类似于android中的下拉加载更多) 每次加载时显示“正在 ...

  4. google官方的下拉刷新&plus;自定义上拉加载更多

    转载请标注转载:http://blog.csdn.net/oqihaogongyuan/article/details/50949118 google官方的下拉刷新+自定义上拉加载更多 现在很多app ...

  5. RecyclerView下拉刷新上拉加载更多

    现在Android里都建议用RecyclerView代替ListView和GridView,所以下拉刷新和上拉加载更多也需要实现.下拉刷新可以用SwipeRefreshLayout 包裹Recycle ...

  6. MVC实现加载更多

    MVC中实现加载更多 作者 欢醉 关注 2016.01.25 08:48 字数 945 阅读 136评论 0喜欢 2 需要实现的功能: 数据太多想初次加载部分数据,在底部加上“加载更多”按钮 点击后加 ...

  7. Android ListView加载更多

    先看效果: ListView的footer布局: <?xml version="1.0" encoding="utf-8"?> <Relati ...

  8. LIstView 滚动 异步 加载更多 mono for android ScrollStateChanged ScrollState&period;Idle&semi; Fling&semi;TouchScroll

    今天项目需要实现一下列表的分页加载 找到了Listview的ScrollStateChanged方法. 和大家分享一下 //先找到Listview ListView order = FindViewB ...

  9. Android 上拉加载更多功能

    前几天看了github上面的例子,参照它的实现,自己又稍微改了一点,往项目里面增加了一个上拉加载更多功能.具体的实现如下: 首先要重写ListView: import android.content. ...

随机推荐

  1. jQuery checkbox的全选与反选

    1:checkbox的全选与反选 js 代码 $("#cbAll").click(function(){ if($("#cbAll").is(":ch ...

  2. 提取ecshop的mysql类

    在下一篇文章中,我还将介绍如何完善ecshop的mysql类,使用ecshop的数据库前缀 下载ecshop后,解压缩,进入目录upload/includes,复制里面的cls_mysql.php放进 ...

  3. Android studio 提高导入项目的速度

    最近在下载了一些开源的项目在学习,在导入as时,速度要好慢,如项目大点,就更慢了,实在是坑啊! 那有没有方法能导入时间快点呀! 分析发现,as在导入项目是首先是读 来自为知笔记(Wiz)

  4. grunt使用watch和livereload的Gruntfile&period;js的配置

    周末在家看angularJS, 用grunt的livereload的自动刷新, 搞了大半天, 现在把配置贴出来, 免得以后忘记了, 只要按照配置一步步弄是没有问题的; 开始的准备的环境安装是: (1) ...

  5. unique mapped reads

    就是指唯一比对的reads 现在人们已经开始避免使用unique mapped reads这个概念了,而转向使用mapq值来保留高质量的比对结果.因为mapq值反应了一组比对结果发生的可能性,MapQ ...

  6. EF ORM

    //新增 UserInfo userInfo = new UserInfo(); userInfo.UserName = "YANG"; userInfo.UserPass = & ...

  7. 【Core内存】&period;NET Core 2&period;0中使用MemoryCache

    说到内存缓存大家可能立马想到了HttpRuntime.Cache,它位于System.Web命名空间下,但是在ASP.NET Core中System.Web已经不复存在.今儿个就简单的聊聊如何在ASP ...

  8. Dubbox:来自当当网的SOA服务框架

    Dubbox:来自当当网的SOA服务框架 http://www.open-open.com/lib/view/open1417426480618.html

  9. python项目运行环境安装小结

    安装最新即可,实际的版本号可能不一样 安装过程较复杂,建议用一台单独的vm安装,能做成docker image最好 基础软件 nginx-1.10.0: sudo apt-get install ng ...

  10. ViewPager &plus; Fragment 实现主界面底部导航栏

    1. 四个类似的Frament布局 tab_main_fragment.xml <LinearLayout xmlns:android="http://schemas.android. ...