Android -- 網路模組中NetworkFactory與NetworkAgent的通訊機制
Android -- NetworkFactory與NetworkAgent的通訊機制
轉自write.blog.csdn.net/postedit在上一篇博文中講到,EthernetNetworkFactory包攬了Ethernet所有的網路管理操作,這其中就包含怎麼樣通知ConnectifyService(下文都簡稱CS)網路狀態發生變化。接下來,我們藉助有線網路來簡要介紹Android 4.4之後,網路模組是怎樣與CS通訊並進行網路管理的。 在啟動Ethernet網路服務時,我們會對Ethernet做一些初始化操作,以方便我們進行網路管理。看EthernetNetworkFactory::start()方法:
- /**
- * Begin monitoring connectivity
- */
- publicsynchronizedvoid start(Context context, Handler target) {
- // The services we use.
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- mNMService = INetworkManagementService.Stub.asInterface(b);
- mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);
- // Interface match regex.
- mIfaceMatch = context.getResources().getString(
- com.android.internal.R.string.config_ethernet_iface_regex);
- // Create and register our NetworkFactory.
- mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());
- mFactory.setCapabilityFilter(mNetworkCapabilities);
- mFactory.setScoreFilter(-1); // this set high when we have an iface
- mFactory.register();
- mContext = context;
- // Start tracking interface change events.
- mInterfaceObserver = new InterfaceObserver();
- try {
- mNMService.registerObserver(mInterfaceObserver);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not register InterfaceObserver " + e);
- }
- // If an Ethernet interface is already connected, start tracking that.
- // Otherwise, the first Ethernet interface to appear will be tracked.
- try {
- final String[] ifaces = mNMService.listInterfaces();
- for (String iface : ifaces) {
- synchronized(this) {
- if (maybeTrackInterface(iface)) {
- // We have our interface. Track it.
- // Note: if the interface already has link (e.g., if we
- // crashed and got restarted while it was running),
- // we need to fake a link up notification so we start
- // configuring it. Since we're already holding the lock,
- // any real link up/down notification will only arrive
- // after we've done this.
- if (mNMService.getInterfaceConfig(iface).hasFlag("running")) {
- updateInterfaceState(iface, true);
- }
- break;
- }
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Could not get list of interfaces " + e);
- }
- }
- /**
- * A NetworkFactory is an entity that creates NetworkAgent objects.
- * The bearers register with ConnectivityService using {@link #register} and
- * their factory will start receiving scored NetworkRequests. NetworkRequests
- * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
- * overridden function. All of these can be dynamic - changing NetworkCapabilities
- * or score forces re-evaluation of all current requests.
- *
- * If any requests pass the filter some overrideable functions will be called.
- * If the bearer only cares about very simple start/stopNetwork callbacks, those
- * functions can be overridden. If the bearer needs more interaction, it can
- * override addNetworkRequest and removeNetworkRequest which will give it each
- * request that passes their current filters.
- * @hide
- **/
- publicclass NetworkFactory extends Handler {
- ...
- public NetworkFactory(Looper looper, Context context, String logTag,
- NetworkCapabilities filter) {
- super(looper);
- LOG_TAG = logTag;
- mContext = context;
- mCapabilityFilter = filter;
- }
- ...
- publicvoid register() {
- if (DBG) log("Registering NetworkFactory");
- if (mMessenger == null) {
- mMessenger = new Messenger(this);
- ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
- }
- }
- ...
- // override to do simple mode (request independent)
- protectedvoid startNetwork() { }
- protectedvoid stopNetwork() { }
- ...
- }
- publicvoid register() {
- if (DBG) log("Registering NetworkFactory");
- if (mMessenger == null) {
- mMessenger = new Messenger(this);
- ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
- }
- }
- @Override
- publicvoid registerNetworkFactory(Messenger messenger, String name) {
- enforceConnectivityInternalPermission();
- NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
- }
- case EVENT_REGISTER_NETWORK_FACTORY: {
- handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
- break;
- }
- privatevoid handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
- if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
- mNetworkFactoryInfos.put(nfi.messenger, nfi);
- nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
- }
- /**
- * Connect handler and messenger.
- *
- * Sends a CMD_CHANNEL_HALF_CONNECTED message to srcHandler when complete.
- * msg.arg1 = status
- * msg.obj = the AsyncChannel
- *
- * @param srcContext
- * @param srcHandler
- * @param dstMessenger
- */
- publicvoid connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
- if (DBG) log("connect srcHandler to the dstMessenger E");
- // We are connected
- connected(srcContext, srcHandler, dstMessenger);
- // Tell source we are half connected
- replyHalfConnected(STATUS_SUCCESSFUL);
- if (DBG) log("connect srcHandler to the dstMessenger X");
- }
- /**
- * Connect handler to messenger. This method is typically called
- * when a server receives a CMD_CHANNEL_FULL_CONNECTION request
- * and initializes the internal instance variables to allow communication
- * with the dstMessenger.
- *
- * @param srcContext
- * @param srcHandler
- * @param dstMessenger
- */
- publicvoid connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
- if (DBG) log("connected srcHandler to the dstMessenger E");
- // Initialize source fields
- mSrcContext = srcContext;
- mSrcHandler = srcHandler;
- mSrcMessenger = new Messenger(mSrcHandler);
- // Initialize destination fields
- mDstMessenger = dstMessenger;
- if (DBG) log("connected srcHandler to the dstMessenger X");
- }
- /**
- * Reply to the src handler that we're half connected.
- * see: CMD_CHANNEL_HALF_CONNECTED for message contents
- *
- * @param status to be stored in msg.arg1
- */
- privatevoid replyHalfConnected(int status) {
- Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
- msg.arg1 = status;
- msg.obj = this;
- msg.replyTo = mDstMessenger;
- /*
- * Link to death only when bindService isn't used.
- */
- if (mConnection == null) {
- mDeathMonitor = new DeathMonitor();
- try {
- mDstMessenger.getBinder().linkToDeath(mDeathMonitor, 0);//為了防止AsyncChannel用於不同程序通訊時,若Server端所在的程序已經死掉,來通知
- //Client端程序進行一些後期處理
- } catch (RemoteException e) {
- mDeathMonitor = null;
- // Override status to indicate failure
- msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
- }
- }
- mSrcHandler.sendMessage(msg);
- }
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
- handleAsyncChannelHalfConnect(msg);
- break;
- }
- privatevoid handleAsyncChannelHalfConnect(Message msg) {
- AsyncChannel ac = (AsyncChannel) msg.obj;
- if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- if (VDBG) log("NetworkFactory connected");
- // A network factory has connected. Send it all current NetworkRequests.
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.isRequest == false) continue;
- NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
- ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
- (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
- }
- } else {
- loge("Error connecting NetworkFactory");
- mNetworkFactoryInfos.remove(msg.obj);
- }
- } elseif (mNetworkAgentInfos.containsKey(msg.replyTo)) {
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- if (VDBG) log("NetworkAgent connected");
- // A network agent has requested a connection. Establish the connection.
- mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
- sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
- } else {
- loge("Error connecting NetworkAgent");
- NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
- if (nai != null) {
- finalboolean wasDefault = isDefaultNetwork(nai);
- synchronized (mNetworkForNetId) {
- mNetworkForNetId.remove(nai.network.netId);
- mNetIdInUse.delete(nai.network.netId);
- }
- // Just in case.
- mLegacyTypeTracker.remove(nai, wasDefault);
- }
- }
- }
- }
- // A network factory has connected. Send it all current NetworkRequests.
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.isRequest == false) continue;
- NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
- ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
- (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
- }
- @Override
- publicvoid handleMessage(Message msg) {
- switch (msg.what) {
- case CMD_REQUEST_NETWORK: {
- handleAddRequest((NetworkRequest)msg.obj, msg.arg1);
- break;
- }
- case CMD_CANCEL_REQUEST: {
- handleRemoveRequest((NetworkRequest) msg.obj);
- break;
- }
- case CMD_SET_SCORE: {
- handleSetScore(msg.arg1);
- break;
- }
- case CMD_SET_FILTER: {
- handleSetFilter((NetworkCapabilities) msg.obj);
- break;
- }
- }
- }
- privatevoid handleAddRequest(NetworkRequest request, int score) {
- NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
- if (n == null) {
- if (DBG) log("got request " + request + " with score " + score);
- n = new NetworkRequestInfo(request, score);
- mNetworkRequests.put(n.request.requestId, n);
- } else {
- if (VDBG) log("new score " + score + " for exisiting request " + request);
- n.score = score;
- }
- if (VDBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
- evalRequest(n);
- }
- privatevoid evalRequest(NetworkRequestInfo n) {
- if (VDBG) log("evalRequest");
- if (n.requested == false && n.score < mScore &&
- n.request.networkCapabilities.satisfiedByNetworkCapabilities(
- mCapabilityFilter) && acceptRequest(n.request, n.score)) {
- if (VDBG) log(" needNetworkFor");
- needNetworkFor(n.request, n.score);
- n.requested = true;
- } elseif (n.requested == true &&
- (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
- mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
- if (VDBG) log(" releaseNetworkFor");
- releaseNetworkFor(n.request);
- n.requested = false;
- } else {
- if (VDBG) log(" done");
- }
- }
- // override to do fancier stuff
- protectedvoid needNetworkFor(NetworkRequest networkRequest, int score) {
- if (++mRefCount == 1) startNetwork();
- }
- protectedvoid releaseNetworkFor(NetworkRequest networkRequest) {
- if (--mRefCount == 0) stopNetwork();
- }
- privateclass LocalNetworkFactory extends NetworkFactory {
- LocalNetworkFactory(String name, Context context, Looper looper) {
- super(looper, context, name, new NetworkCapabilities());
- }
- protectedvoid startNetwork() {
- onRequestNetwork();
- }
- protectedvoid stopNetwork() {
- }
- }
- /* Called by the NetworkFactory on the handler thread. */
- publicvoid onRequestNetwork() {
- // TODO: Handle DHCP renew.
- Thread dhcpThread = new Thread(new Runnable() {
- publicvoid run() {
- if (DBG) Log.i(TAG, "dhcpThread(" + mIface + "): mNetworkInfo=" + mNetworkInfo);
- LinkProperties linkProperties;
- IpConfiguration config = mEthernetManager.getConfiguration();
- if (config.getIpAssignment() == IpAssignment.STATIC) {
- if (!setStaticIpAddress(config.getStaticIpConfiguration())) {
- // We've already logged an error.
- return;
- }
- linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);
- } else {
- mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
- DhcpResults dhcpResults = new DhcpResults();
- // TODO: Handle DHCP renewals better.
- // In general runDhcp handles DHCP renewals for us, because
- // the dhcp client stays running, but if the renewal fails,
- // we will lose our IP address and connectivity without
- // noticing.
- if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
- Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
- // set our score lower than any network could go
- // so we get dropped.
- mFactory.setScoreFilter(-1);
- // If DHCP timed out (as opposed to failing), the DHCP client will still be
- // running, because in M we changed its timeout to infinite. Stop it now.
- NetworkUtils.stopDhcp(mIface);
- return;
- }
- linkProperties = dhcpResults.toLinkProperties(mIface);
- }
- ...
- }
- });
- dhcpThread.start();
- }
- synchronized(EthernetNetworkFactory.this) {
- if (mNetworkAgent != null) {
- Log.e(TAG, "Already have a NetworkAgent - aborting new request");
- return;
- }
- mLinkProperties = linkProperties;
- mNetworkInfo.setIsAvailable(true);
- mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
- // Create our NetworkAgent.
- mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,
- NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,
- NETWORK_SCORE) {
- publicvoid unwanted() {
- synchronized(EthernetNetworkFactory.this) {
- if (this == mNetworkAgent) {
- NetworkUtils.stopDhcp(mIface);
- mLinkProperties.clear();
- mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null,
- mHwAddr);
- updateAgent();
- mNetworkAgent = null;
- try {
- mNMService.clearInterfaceAddresses(mIface);
- } catch (Exception e) {
- Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
- }
- } else {
- Log.d(TAG, "Ignoring unwanted as we have a more modern " +
- "instance");
- }
- }
- };
- };
- }
- /**
- * Called when ConnectivityService has indicated they no longer want this network.
- * The parent factory should (previously) have received indication of the change
- * as well, either canceling NetworkRequests or altering their score such that this
- * network won't be immediately requested again.
- */
- abstractprotectedvoid unwanted();
- public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
- NetworkCapabilities nc, LinkProperties lp, int score) {
- this(looper, context, logTag, ni, nc, lp, score, null);
- }
- public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
- NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
- super(looper);
- LOG_TAG = logTag;
- mContext = context;
- if (ni == null || nc == null || lp == null) {
- thrownew IllegalArgumentException();
- }
- if (VDBG) log("Registering NetworkAgent");
- ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
- new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
- }
- publicint registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
- LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
- int currentScore, NetworkMisc networkMisc) {
- enforceConnectivityInternalPermission();
- // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
- // satisfies mDefaultRequest.
- final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
- new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(
- linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,
- mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
- synchronized (this) {
- nai.networkMonitor.systemReady = mSystemReady;
- }
- addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network);
- if (DBG) log("registerNetworkAgent " + nai);
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
- return nai.network.netId;
- }
- case EVENT_REGISTER_NETWORK_AGENT: {
- handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
- break;
- }
- privatevoid handleRegisterNetworkAgent(NetworkAgentInfo na) {
- if (VDBG) log("Got NetworkAgent Messenger");
- mNetworkAgentInfos.put(na.messenger, na);
- synchronized (mNetworkForNetId) {
- mNetworkForNetId.put(na.network.netId, na);
- }
- na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
- NetworkInfo networkInfo = na.networkInfo;
- na.networkInfo = null;
- updateNetworkInfo(na, networkInfo);//更新網路狀態的函式
- }
- if (VDBG) log("NetworkAgent connected");
- // A network agent has requested a connection. Establish the connection.
- mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
- sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
- case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
- if (mAsyncChannel != null) {
- log("Received new connection while already connected!");
- } else {
- if (VDBG) log("NetworkAgent fully connected");
- AsyncChannel ac = new AsyncChannel();
- ac.connected(null, this, msg.replyTo);
- ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
- AsyncChannel.STATUS_SUCCESSFUL);
- synchronized (mPreConnectedQueue) {
- mAsyncChannel = ac;
- for (Message m : mPreConnectedQueue) {
- ac.sendMessage(m);
- }
- mPreConnectedQueue.clear();
- }
- }
- break;
- }
- publicvoid connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
- if (DBG) log("connected srcHandler to the dstMessenger E");
- // Initialize source fields
- mSrcContext = srcContext;
- mSrcHandler = srcHandler;
- mSrcMessenger = new Messenger(mSrcHandler);
- // Initialize destination fields
- mDstMessenger = dstMessenger;
- if (DBG) log("connected srcHandler to the dstMessenger X");
- }
- publicvoid updateAgent() {
- synchronized (EthernetNetworkFactory.this) {
- if (mNetworkAgent == null) return;
- if (DBG) {
- Log.i(TAG, "Updating mNetworkAgent with: " +
- mNetworkCapabilities + ", " +
- mNetworkInfo + ", " +
- mLinkProperties);
- }
- mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
-
相關推薦
Android -- 網路模組中NetworkFactory與NetworkAgent的通訊機制
Android -- NetworkFactory與NetworkAgent的通訊機制 轉自write.blog.csdn.net/postedit 在上一篇博文中講到,EthernetNetworkFactory包攬了Ethernet所有的網路管理操作,這其中就包含怎麼樣通知ConnectifyServi
socket網路程式設計中伺服器與客戶端通訊失敗的問題
伺服器程式碼如下 public class server { public static void main(String[] args) throws IOException { ServerSocket server=new S
Android網路程式設計中的URLConnection的IP設定
虛擬機器測試:10.0.0.2 PC連線乙太網:通過cmd命令,進入命令視窗。輸入ipconfig檢視乙太網介面卡ipv4地址 Android測試機連入本機WiFi網路:如圖 如果Android上提示 java.net.SocketTimeoutEx
WPF中MainWindow與Page通訊
與WinForm不同,WPF拋棄了MDIwindow的概念,因為微軟的工程師們相信主視窗加可以切換的Page,也就象是標籤頁似的結構,才更符合人們使用的習慣。剛好前一階段需要設計一個軟體介面,需要實現不同功能介面的切換功能,我用了MainWindow->F
網路程式設計中阻塞與非阻塞、同步與非同步、I/O模型的理解
1. 概念理解 在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unblock)四種呼叫方式:同步:所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。也就是必須一件一件事做,等前一件做完了才能做下一件事。 例如
Android網路程式設計中關於AsyncHttpClient獲取cookie的問題
之前的專案登入模組存在問題,登入狀態和使用者名稱直接存在了SharedPreferences裡,進入軟體時直接判斷使用者名稱是否為空,為空時才進入登入頁面,否則直接讀取SP中的相關資料,看了AsyncHttpClient的文件後,才發現可以允許讀取cookie。
android網路程式設計中使用java的回撥機制
1) 先定義一個介面 public interface HttpCallbackListener { void onFinish(String response); void onError(Exception e); } 2) 在工具類HttpUtil中
Android網路傳輸中必用的兩個加密演算法:MD5 和 RSA (附java完成測試程式碼)
MD5和RSA是網路傳輸中最常用的兩個演算法,瞭解這兩個演算法原理後就能大致知道加密是怎麼一回事了。但這兩種演算法使用環境有差異,剛好互補。一、MD5演算法首先MD5是不可逆的,只能加密而不能解密。比如明文是yanzi1225627,得到MD5加密後的字串是:14F2AE15
Windows網路程式設計中Socket與WSASocket區別
這2個函式的主要功能都是建立一個SOCKET,函式定義分別如下: SOCKET WSAAPI socket( _In_ int af, _In_ int type, _In_ int pr
納稅服務投訴受理模組中投訴與回覆中的級聯查詢等細節
1、投訴和投訴回覆實體及hbm配置檔案 Complain.java package cn.buaa.nsfw.complain.entity; import java.sql.Timestamp; import java.util.HashMap; import jav
Android網路程式設計(使用socket進行通訊)
Socket就是網路套接字程式設計,網路程式設計簡單的理解就是兩臺計算機相互通訊資料而已。對於程式設計師而言,去掌握一種程式設計介面並使用一種程式設計模型相對就會顯得簡單的多了.Java SDK提供一些相對簡單的Api來完成這些工作,這些Api存在與java.n
Android每天一個知識點+Demo—跨程序通訊機制AIDL入門
一 Why-為什麼要用AIDL 沙箱理念:在Android中,每個應用(Application)程式都執行在獨立的程序中,無法直接呼叫到其他應用的資源。當一個應用被執行時,一些操作是被限制的,比如訪問記憶體,訪問感測器等等。 好處:這也保證了當其中一個程式出現異常而不會影
Android安全/開發基礎--6--程序間通訊機制(IPC)
6-1、多程序 1、多程序分為兩種: 第一種情況是一個應用因為某些原因自身需要採用多執行緒模式來實現。 另一種情況是當前應用需要向其他應用獲取資料。 2、Android中的多程序模式: 通過給四大元件指定android:process屬性,可以開啟多程序模式,使
Android進階:網路與資料儲存—步驟1:Android網路與通訊(第2小節:Handler)
內容概覽 Handler是什麼 為什麼要使用Handler Handler/Looper/MessageQueue/Message Handler如何去實現(三種實現:1、下載檔案並更新進度條 2、倒計時 3、打地鼠的遊戲實現) 工作原理 如果更好的使用 擴充套
Android進階:網路與資料儲存—步驟1:Android網路與通訊(第3小節:ListView上)
內容概要: 一、課程介紹 二、ListView的準備工作 ListView簡介 ListView的實現步驟 三、ListView簡單應用 Adapter的資料繫結 最簡單ListView效果演示 獲取系統已安裝應用列表 優化效能 一、課程介紹 什麼是List
Android進階:網路與資料儲存—步驟1:Android網路與通訊(第4小節:ListView下)
內容概括: 一、網路下載資料並顯示在ListView上 使用非同步訪問網路 解析獲取的Json資料 載入資料到ListView上 二、不同item的引用 引用不同行佈局 一、網路下載資料並顯示在ListView上 1.1-使用非同步訪問網路 //非同步訪問網路
Android進階:網路與資料儲存—步驟1:Android網路與通訊(第6小節:GridView)
內容概要: GirdView(網格檢視)顯示本地資料 GirdView屬性簡介 案例一:用GirdView展示文字 案例二:用GridView顯示已安裝應用 GridView顯示網路 用GridView載入網路圖片(上) 用GridView載入網路圖片(下) 一、
Android進階:網路與資料儲存—步驟1:Android網路與通訊(第7小節:CadView)
內容概要: CardView基礎 CardView介紹 CardVie常用屬性 CardView屬性效果展示 CardView案例實現 CardVie基本操作 案例-佈局搭建 案例-實體類建立 案例-功能實現 案例-適配 CardView開發注意事項 一、Ca
node.js中net網路模組TCP服務端與客戶端的使用
node.js中net模組為我們提供了TCP伺服器和客戶端通訊的各種介面。 一、建立伺服器並監聽埠 const net = require('net'); //建立一個tcp服務 //引數一表示建立服務的一些配置 //引數二表示 事件 'connection' 監聽回撥函式
android中fragment與activity之間通訊原理以及例子
首先,如果你想在android3.0及以下版本使用fragment,你必須引用android-support-v4.jar這個包 然後你寫的activity不能再繼承自Activity類了,而是要繼承android.support.v4.app.FragmentA