java中的回撥CallBack,Thread以及與android的關聯
- class A實現介面InA
- class A中包含一個class B的引用b
- class B有一個引數為InA的方法test(InA a)
- A的物件a呼叫B的方法傳入自己,test(a) ——這一步相當於you call me
- 然後b就可以在test方法中呼叫InA的方法 ——這一步相當於i call you back
再來定義實現了CallBack介面的class A,定義為Boss類,我們模擬的場景是,Boss手下有一個員工Employee,Boss在某個時刻想要讓員工去幫他買東西,當員工買完後將把結果告知給Boss,也就是我們所說的回撥,通過回撥函式的solve()方法將結果給Boss。
Boss類在建立的時候需要傳入一個員工物件Employee,在需要的時候,會呼叫Employee的方法,讓他來處理邏輯,Employee如下:
當想要呼叫Employee的buySomething方法時,需要傳入Callback介面的實現類,邏輯處理完畢後則呼叫Callback介面的方法回傳結果,編寫測試類,測試結果如下:
其實在Java中,執行緒Thread的原理也是使用了回撥機制,我們可以來看下面這個最簡單的執行緒例項:
我們先進入Runnable程式碼中去看,可以發現他是個介面:new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start();
@FunctionalInterface public interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); }
我們將Runnable的實現類當做引數傳入給Thread類,Thread的start()方法會回撥Runnable實體類的run方法來進行邏輯處理,但是我們卻發現了一個奇怪的事情,那就是Thread類已經實現了Runnable介面,卻還要傳入Runnable的實現類,這是為什麼?原來這是java中的代理模式!!!
繼承Thread類方式和通過Runnable介面的方式
繼承Thread類方式的缺點:如果我們的類已經繼承了其他類,那就無法再繼承Thread類了
實現Runnable介面的方式優點:避免了單繼承,方便共享資源,同一份資源可以有多個代理訪問
代理就比如是找房子可以找中介,結婚可以找婚慶公司。
在靜態代理模式中有兩個角色
1:真實角色
2:代理角色
兩個角色通過實現相同的介面來實現關聯
下面可以看一個例子://真實角色
class You implements IMarry{
@Override
public void marry() {
}
}
代理角色class WeddingCompany implements IMarry{
@Override
public void marry() {
}
}
讓代理模式持有真實角色的引用
class WeddingCompany implements IMarry {
private IMarry you;
public WeddingCompany(){}
public WeddingCompany(IMarry you){
this.you=you;
}
@Override
public void marry() {
you.marry();
}
}
使用例項程式碼public static void main(String[] args) {
//建立真實角色
IMarry you=new You();
//建立代理角色加入真實角色的引用
WeddingCompany weddingCompany=new WeddingCompany(you);
}
此時讓我們進入Thread的建構函式來去看看:
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
繼續往下找,就能看到初始化Runnable物件的程式碼(中間省略):
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
...
this.target = target;
setPriority(priority);
...
}
好了,我們可以看到Thread的建構函式將Runnable的例項物件初始化給了成員變數,我們都知道要啟動一個執行緒需要呼叫start()方法,我們看下start()方法做了什麼:
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
具體程式碼不做研究,start()方法呼叫作業系統本地的執行緒啟動方法,使得run()方法內部的程式碼執行在非同步執行緒中,我們都知道執行緒啟動有兩種方法,start()和run(),start方法正常啟動非同步執行緒,而run方法雖然同樣執行了內部的所有操作,但確實跟主執行緒同步執行的,無法進行非同步操作,我們看下Thread的run方法就知道為什麼了:
/**
* If this thread was constructed using a separate
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called;
* otherwise, this method does nothing and returns.
* <p>
* Subclasses of <code>Thread</code> should override this method.
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
這樣我們就能看出所以然了,Thread的run方法居然只是簡單地呼叫了傳入的Runnable物件的run方法,並沒有開啟非同步執行緒。 關於Thread的幾種常用方式可以看下網上的部落格,一般都是兩種方法:直接繼承Thread重寫run方法或者實現Runnable介面寫run方法,兩種區別就是,實現Runnable介面適用於多執行緒對於同一個資料進行操作,例如我們常見的賣票系統等。
本篇主要是說回撥的使用,有些跑偏了,那麼android中是否存在回撥呢? 必須得啊,我們天天都在使用的OnClickListener,OnLongClickListener等一系列方法都是回撥方法,首先我們看下回調介面:
/**
* Interface definition for a callback to be invoked when a view is clicked.
*/
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}
對,沒錯,就是View類中的OnClickListener介面,這個介面唯一的方法:onClick也就是回撥函式用於我們處理點選事件的邏輯,當一個View發生點選事件時,就會回撥onClick方法,我們就可以在Activity進行邏輯處理。下面我們模擬一下這個場景,首先定義抽象介面和view如下:
//點選事件的介面
public interface OnClickListener {
public void onclick();
}
//view類,儲存實現事件介面的實體物件,在適當的時候呼叫介面方法,回傳點選事件
public class View{
private OnClickListener listener;
public void performClick(){
listener.onclick();
}
public void SetOnClickListener(OnClickListener l){
listener=l;
}
}
實際情況中OnClickListener是定義在View類的內部,但這裡我們為了更好地看清楚回撥函式的使用,將其分開來了。View中定義了兩個方法,SetOnClickListener用來將onClickListener的例項物件與其繫結,也就是獲得例項物件,當用戶進行點選操作時performClick方法就會被呼叫,然後回撥介面的onclick方法。
下面是Activity的定義:
//Activity實現點選事件的介面,用來接收view的點選事件
public class Activity implements OnClickListener{
private View view;
public Activity(){
view=new View();
view.SetOnClickListener(this);
}
public void onclick(){
System.out.println("view點選一次");
}
public void clickOnce(){
view.performClick();
}
}
Activity實現了介面OnClickListener,並定義了一個view,呼叫view的SetOnClickListener方法將自己傳入,然後我們模擬點選事件,clickOnce呼叫時,就會呼叫view的performClick方法,然後view會回撥onclick(),如下:
/**
* @param args
*/
public static void main(String[] args) {
Activity activity=new MyActivity().new Activity();
activity.clickOnce();
}
當然我們只是非常簡單地模擬點選事件,不過原理就是我們上面所講述的:回撥!!!可見回撥在程式設計中是非常重要的一個知識點。在android開發中要結合java的特性來思考,以前只會簡單地呼叫view.setOnClickListener(),不明白其中的原理,現在一定要多想多思考。
相關推薦
java中的回撥CallBack,Thread以及與android的關聯
class A實現介面InA class A中包含一個class B的引用bclass B有一個引數為InA的方法test(InA a) A的物件a呼叫B的方法傳入自己,test(a) ——這一步相當於you call me然後b就可以在test方法中呼叫InA的方法 —
關於對Java中回撥函式的理解
先來看幾段程式: 1. 首先定義一個類Caller,這個類裡面儲存一個介面引用。 public class Caller { private MyCallInter
回撥函式,函式指標與函式物件
1. 什麼是回撥函式 回撥函式(callback Function),顧名思義,用於回撥的函式。 回撥函式只是一個功能片段,由使用者按照回撥函式呼叫約定來實現的一個函式。回撥函式是一個工作流的一部分,由工作流來決定函式的呼叫(回撥)時機。回撥函 數包含下面
java回撥原理,以及Callable和FutureTask通過回撥機制建立可監控的執行緒
回撥的概念會JS的人應該都能理解。 回撥分非同步回撥,同步回撥。但是同步回撥其實沒什麼意義。都同步了,那麼直接等那邊執行完了,這邊再執行就可以了,沒必要通過回撥。我們說的回撥主要是講非同步回撥。用於兩個執行緒甚至兩個系統之間互動呼叫。 例如我在A類的方法funa()中,要呼叫B類的方法fun
安卓(Android)中如何優雅的 建立/執行 非同步任務/回撥(AsyncTask 、Thread、Job、CallBack、Handler) ?執行緒池(Executor)
How to use? 1、first step: copy the file "ExcuteTaskManager" and "ExcuteTask" to your project 2、second step: init the library in your application or
Java執行緒之非同步回撥(Callback)
●介紹 有時候執行一個任務需要很長時間,單執行緒下執行緒會處於阻塞狀態。這個時候我們會考慮一種非阻塞的處理模式。非阻塞任務在任何程式語言裡都必不可少,Java也不例外。多執行緒就是一個很好的解決辦法。
C++ | callback回撥函式,函式名做引數傳遞
在js中的回撥函式已經是隨處可見了,像下面這樣 // js callback demo function foo(value){ console.log(value) } function inject(callback){ var value = 'hello!
Java程式設計之委託代理回撥、內部類以及匿名內部類回撥(閉包回撥)
最近一直在看Java的相關東西,因為我們在iOS開發是,無論是Objective-C還是Swift中,經常會用到委託代理回撥,以及Block回撥或者說是閉包回撥。接下來我們就來看看Java語言中是如何實現委託代理回撥以及閉包回撥的。當然這兩個技術點雖然實現起來並不困難,但是,這回調在封裝一些公用元件時還是特別
vue中使用回撥函式,this呼叫無效
let self = this //使用新變數替換this,以免this無效//updateStudentInfoToServer是一個將本身部分資料非同步上傳的介面,this.updateStudentInfoToServer(data, function(res){
java中繼承的理解,super關鍵字,方法的重寫和過載以及注意事項理解
一、類的繼承理解 在java中類的繼承是指:在一個現有類的基礎之上去構建一個新的類,構建出來的新的類被稱為子類,現有類是父類,子類會自動擁有父類所有可繼承的屬性和方法。繼承類是現有類的更具體一些,繼承類可能只擁有一部分父類的屬性和方法。 如圖,這就表示了繼承類是父類的一種更具體形式
android網路程式設計中使用java的回撥機制
1) 先定義一個介面 public interface HttpCallbackListener { void onFinish(String response); void onError(Exception e); } 2) 在工具類HttpUtil中
Zookeeper Java API (三) zk節點的通知(Watcher)和回撥(CallBack)
Zk中的通知(Watcher) ZooKeeper中實現對接點的監控,需要實現Watcher介面類,實現其中的process方法 public class WatcherDemo implements Watcher{ public void p
Android ndk jni中回撥java的方法&欄位描述符
一、jobject和jclass 1.如果定義native方法時使用了static關鍵字,那麼生成的標頭檔案裡就會傳入jclass,代表這個類的引用。 2.如果沒有使用static關鍵字,那麼就會傳入jobject,代表類的物件的引用。 二、jni回撥
Android finish()自動回撥時機,Activity資源釋放邏輯放在onDestroy中一定合適嗎
首先看Google對finish()的描述, Call this when your activity is done and should be closed. The ActivityResult is propagated back
JAVA的回撥函式和反射機制(原理不說直接看程式碼),補充動靜態代理
程式碼都是轉載或抄錄這個地址: http://blog.csdn.net/zhandoushi1982/article/details/8567709 http://blog.csdn.net/xiaanming/article/details/8703708/ 反射機制
Android介面回撥總結,以及運用到彈窗PopWindow的Demo實現
背景: 最近專案中接觸到介面回撥,以及Android彈窗PopWindow元件的使用,現在利用學到的知識自己寫了一個簡單的Demo,練習下在Android下如何運用介面回撥,來實現彈窗PopWindow的功能。 程式碼結構: 1. 定義一個介面:OnSelectIt
面試官問我“Java中的鎖有哪些?以及區別”,我跪了
讀寫鎖 queue get 吞吐量 參考 示例 事情 自動 高並發 在讀很多並發文章中,會提及各種各樣鎖如公平鎖,樂觀鎖等等,這篇文章介紹各種鎖的分類。介紹的內容如下: 公平鎖/非公平鎖 可重入鎖 獨享鎖/共享鎖 互斥鎖/讀寫鎖 樂觀鎖/悲觀鎖 分段鎖 偏
java中jsp的EL的定義以及使用
eve ext ges tar lis 簡易 resp 必須 xpath 1、定義: EL(Expression Language) 是為了使JSP寫起來更加簡單。表達式語言的靈感來自於 ECMAScript 和 XPath 表達式語言,它提供了在 JSP 中簡化表
在drawRect:方法中繪制圖片,文字以及Core Graphics 框架的了解
graphic csg line 要求 arc 畫圖 cgrect 有一個 get p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 } p.p2 { margin: 0.0
java中常見的類,接口,包,異常
tex 權限 array 變量 都是 run 做的 pointer 數組下標 java中常見的類,接口,包,異常 類 String Integer Long File Date Thread(java.lang.