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關於今天的內容介紹到此介紹,內容很簡單,大家感興趣的話可以實現一下。新手學習,高手交流。
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的協助,同時也希望多多支援雲棲社區!