編輯:關於Android編程
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關於今天的內容介紹到此介紹,內容很簡單,大家感興趣的話可以實現一下。新手學習,高手交流。
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持本站!
很多朋友在啟動應用或者玩游戲的時候都出現Google Play服務已停止運行,或者之前運行正常的應用突然不能使用了。這是為什麼?在這我們就來講解一下Goog
Location Strategies注:本指南中描述的策略適用於平台定位API中android.location。該谷歌位置服務API,谷歌Play的一部分服務,提供了
當一個Touch事件發生,系統首先把事件傳遞給當前的Activity,由Activity的dispatchTouchEvent分發事件,源碼如下: public
基礎知識度量聲音強度,大家最熟悉的單位就是分貝(decibel,縮寫為dB)。這是一個無綱量的相對單位,計算公式如下:分子是測量值的聲壓,分母是參考值的聲壓(20微帕,人