What is 'Context' on Android?html
Putting it simply:java
As the name suggests, it's the context of current state of the application/object. It lets newly-created objects understand what has been going on. Typically you call it to get information regarding another part of your program (activity and package/application).android
You can get the context by invoking getApplicationContext(), getContext(), getBaseContext() or this (when in the activity class).git
Typical uses of context:web
•Creating new objects: Creating new views, adapters, listeners:
TextView tv = new TextView(getContext());
ListAdapter adapter = new SimpleCursorAdapter(getApplicationContext(), ...);數據庫
•Accessing standard common resources: Services like LAYOUT_INFLATER_SERVICE, SharedPreferences:
context.getSystemService(LAYOUT_INFLATER_SERVICE)
getApplicationContext().getSharedPreferences(*name*, *mode*);瀏覽器
•Accessing components implicitly: Regarding content providers, broadcasts, intent
getApplicationContext().getContentResolver().query(uri, ...);緩存
=====
Definition of Context::
•Context represents environment data
•It provides access to things such as databases安全
Simpler terms :: 服務器
•Consider Person-X is the CEO of a start-up software company.
•There is a lead architect present in the company, this lead architect does all the work in the company which involves such as database, UI etc.
•Now the CEO Hires a new Developer.
•It is the Architect who tells the responsibility of the newly hired person based on the skills of the new person that whether he will work on Database or UI etc.
Simpler terms ::
•It's like access of android activity to the app's resource.
•It's similar to when you visit a hotel, you want breakfast, lunch & dinner in the suitable timings, right?
•There are many other things you like during the time of stay. How do you get these things?
•You ask the room-service person to bring these things for you.
•Here the room-service person is the context considering you are the single activity and the hotel to be your app, finally the breakfast, lunch & dinner have to be the resources.
Things that involve context are:
1.Loading a resource.
2.Launching a new activity.
3.Creating views.
4.obtaining system service.
Context is the base class for Activity, Service, Application .... etc
Another way to describe this: Consider context as remote of a TV & channel's in the television are resources, services, using intents etc - - - Here remote acts as an access to get access to all the different resources into foreground.
•So, Remote has access to channels such as resources, services, using intents etc ....
•Likewise ..... Whoever has access to remote naturally has access to all the things such as resources, services, using intents etc
Different invoking methods by which you can get context
•getApplicationContext()
•getContext()
•getBaseContext()
•or this (when in the activity class)
Example:
TextView TV=new TextView(this);
this -> refers to the context of the current activity.
=========
The topic of Context in Android seems to be confusing too many. People just know that Context is needed quite often to do basic things in Android. People sometimes panic because they try to do perform some operation that requires the Context and they don’t know how to 「get」 the right Context. I’m going to try to demystify the idea of Context in Android. A full treatment of the issue is beyond the scope of this post, but I’ll try to give a general overview so that you have a sense of what Context is and how to use it. To understand what Context is, let’s take a look at the source code:
http://codesearch.google.com/codesearch#search&q=package:android.git.kernel.org+file:android/content/Context.java
What exactly is Context?
Well, the documentation itself provides a rather straightforward explanation: The Context class is an 「Interface to global information about an application environment".
The Context class itself is declared as abstract class, whose implementation is provided by the Android OS. The documentation further provides that Context 「…allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc".
You can understand very well, now, why the name is Context. It’s because it’s just that. The Context provides the link or hook, if you will, for an Activity, Service, or any other component, thereby linking it to the system, enabling access to the global application environment. In other words: the Context provides the answer to the components question of 「where the hell am I in relation to app generally and how do I access/communicate with the rest of the app?」 If this all seems a bit confusing, a quick look at the methods exposed by the Context class provides some further clues about its true nature.
Here’s a random sampling of those methods: 1. getAssets() 2. getResources() 3. getPackageManager() 4. getString() 5. getSharedPrefsFile()
What do all these methods have in common? They all enable whoever has access to the Context to be able to access application-wide resources.
Context, in other words, hooks the component that has a reference to it to the rest of application environment. The assets (think ’/assets’ folder in your project), for example, are available across the application, provided that an Activity, Service or whatever knows how to access those resources. Same goes for 「getResources()」 which allows to do things like 「getResources().getColor()」 which will hook you into the colors.xml resource (nevermind that aapt enables access to resources via java code, that’s a separate issue).
The upshot is that Context is what enables access to system resources and its what hooks components into the 「greater app". Let’s look at the subclasses of Context, the classes that provide the implementation of the abstract Context class. The most obvious class is the Activity class. Activity inherits from ContextThemeWrapper, which inherits from ContextWrapper, which inherits from Context itself. Those classes are useful to look at to understand things at a deeper level, but for now it’s sufficient to know that ContextThemeWrapper and ContextWrapper are pretty much what they sound like. They implement the abstract elements of the Context class itself by 「wrapping」 a context (the actual context) and delegating those functions to that context. An example is helpful - in the ContextWrapper class, the abstract method 「getAssets」 from the Context class is implemented as follows:
@Override
public AssetManager getAssets() {
return mBase.getAssets();
}
mBase is simply a field set by the constructor to a specific context. So a context is wrapped and the ContextWrapper delegates its implementation of the getAssets method to that context. Let’s get back to examining the Activity class which ultimately inherits from Context to see how this all works.
You probably know what an Activity is, but to review - it’s basically 'a single thing the user can do. It takes care of providing a window in which to place the UI that the user interacts with'. Developers familiar with other APIs and even non-developers might think of it vernacularly as a 「screen.」 That’s technically inaccurate, but it doesn’t matter for our purposes. So how do Activity and Context interact and what exactly is going in their inheritance relationship?
Again, it’s helpful to look at specific examples. We all know how to launch Activities. Provided you have 「the context」 from which you are you are starting the Activity, you simply call startActivity(intent), where the Intent describes the context from which you are starting an Activity and the Activity you’d like to start. This is the familiar startActivity(this, SomeOtherActivity.class).
And what is 「this」? 「this」 is your Activity because the Activity class inherits from Context. The full scoop is like this: When you call startActivity, ultimately the Activity class executes something like this:
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode);
Ok, so it utilizes the execStartActivity from the Instrumentation class (actually from an inner class in Instrumentation called ActivityResult).
At this point we are beginning to get a peek at the system internals.
This is where OS actually handles everything. So how does Instrumentation start the Activity exactly? Well, the param 「this」 in the execStartActivity method above is the your Activity, i.e. the Context, and the execStartActivity makes use of this context.
A 30,000 overview is this: the Instrumentation class keeps tracks of a list of Activities that it’s monitoring in order to do it’s work. This list is used to coordinate all of the activities and make sure everything runs smoothly in managing the flow of activities.
There are some operations which I haven’t fully looked into which coordinate thread and process issues. Ultimately, the ActivityResult uses a native operation - ActivityManagerNative.getDefault().startActivity() which uses the Context that you passed in when you called startActivity. The context you passed in is used to assist in 「intent resolution」 if needed. Intent resolution is the process by which the system can determine the target of the intent if it is not supplied. (Check out the guide here for more details).
And in order for Android to do this, it needs access to information that is supplied by Context. Specifically, the system needs to access to a ContentResolver so it can 「determine the MIME type of the intent’s data". This whole bit about how startActivity makes use of context was a bit complicated and I don’t fully understand the internals myself. My main point was just to illustrate how application-wide resources need to be accessed in order to perform many of the operations that are essential to an app. Context is what provides access to these resources. A simpler example might be Views. We all know what you create a custom View by extending RelativeLayout or some other View class, you must provide a constructor that takes a Context as an argument. When you instantiate your custom View you pass in the context. Why? Because the View needs to be able to have access to themes, resources, and other View configuration details. View configuration is actually a great example. Each Context has various parameters (fields in Context’s implementations) that are set by the OS itself for things like the dimension or density of the display. It’s easy to see why this information is important for setting up Views, etc.
One final word: For some reason people new to Android (and even people not so new) seem to completely forget about object-oriented programming when it comes to Android. For some reason, people try to bend their Android development to pre-conceived paradigms or learned behaviors.
Android has it’s own paradigm and a certain pattern that is actually quite consistent if let go of your pre-conceived notions and simply read the documentation and dev guide. My real point, however, while 「getting the right context」 can sometimes be tricky, people unjustifiably panic because they run into a situation where they need the context and think they don’t have it. Once again, Java is an object-oriented language with an inheritance design.
You only 「have」 the context inside of your Activity because your activity itself inherits from Context. There’s no magic to it (except for the all the stuff the OS does by itself to set various parameters and to correctly 「configure」 your context). So, putting memory/performance issues aside (e.g. holding references to context when you don’t need to or doing it in a way that has negative consequences on memory, etc), Context is an object like any other and it can be passed around just like any POJO (Plain Old Java Object). Sometimes you might need to do clever things to retrieve that context, but any regular Java class that extends from nothing other than Object itself can be written in a way that has access to context; simply expose a public method that takes a context and then use it in that class as needed. This was not intended as an exhaustive treatment on Context or Android internals, but I hope it’s helpful in demystifying Context a little bit.
=========
有寫過android的人,對context必定不陌生
可是context的用法與時機卻不必定能搞的清楚
到底該用this,還是用ClassName.this,還是用getActivity(),還是用getApplicationContext()呢?
android學習—— context 和 getApplicationContext()
[通常問題] Android基礎概念Context的做用
看到不少Android程序裏面傳Context對象,但不知道這個對象怎麼理解,對應AP的實例仍是什麼其它?
difference between this, Class.this and getApplicationContext
============
今天在項目中發現一個BUG
在使用新浪微博帳戶登陸應用時,webview會自動登陸上次的微博賬號!(由於webview 記錄了微博賬號和密碼的cookies)
因此,須要清除SessionCookie:
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
CookieManager.getInstance().removeSessionCookie();
另外,清理cache和歷史記錄 的方法:
webView.clearCache(true);
webView.clearHistory();
===========
最近項目中遇到用webView顯示內容的需求,接到任務後代碼以下
// 更新加載進度條
wv_setmeal_detail.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
pb_webview.setProgress(progress);
if (progress == 100) {
pb_webview.setVisibility(View.GONE);
}
}
});
wv_setmeal_detail.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(self, "Oh no! " + description, Toast.LENGTH_SHORT).show();
}
});
// 加載網頁
wv_setmeal_detail.loadUrl(url);
嗯,沒問題,顯示的很好,可是測試時發現一個坑爹的問題,就是退出當前帳號換其餘帳號登陸時webview顯示的內容仍是以前帳號的信息,額...怪了.想一想確定是緩存搞的鬼,好,接下來就是清除緩存.
網上各類google baidu,發現不少方法都無論用.作法通常以下
1.websettings設置不適用緩存
mCurrentWebView.clearCache(true);
mCurrentWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
其實無論用...
2.webview顯示時會自動生成以下文件 data/data/<包名>/app_webview
而後就是循環遍歷刪除該文件下的內容
/**
* 清除WebView緩存
*/
public void clearWebViewCache() {
// WebView 緩存文件
File appCacheDir = new File(DATA_BASE_PATH + getPackageName() + APP_WEBVIEW_PATH);
if (appCacheDir.exists()) {
deleteFile(appCacheDir);
}
}
/**
* 遞歸刪除 文件/文件夾
*
* @param file
*/
public void deleteFile(File file) {
if (file.exists()) {
if (file.isFile()) {
file.delete();
} else if (file.isDirectory()) {
File files[] = file.listFiles();
for (int i = 0; i < files.length; i++) {
deleteFile(files[i]);
}
}
file.delete();
}
}
發現推出後立刻切換行,過一分鐘左右仍是不行.
就鬱悶了...到底緩存數據存在哪了呢...
最後google在stackoverflow上看到一篇文章,問題得以解決.原來是要清除webview的cookie才能完全把緩存清除
public void clearWebViewCache() {
// 清除cookie便可完全清除緩存
CookieSyncManager.createInstance(self);
CookieManager.getInstance().removeAllCookie();
}
附上兩篇文章地址
http://stackoverflow.com/questions/2465432/Android-webview-completely-clear-the-cache
http://www.devdiv.com/forum.PHP?mod=viewthread&tid=116641
========
Android應用註銷會話後清除WebView中Cookies
Android應用使用WebView控件瀏覽網頁,用戶登陸帳戶後會將Cookie存入/data/data/<package_name>/databases/webviewCookiesChromium.db的cookies表中。應用退出後不會自動清理cookie,若是cookie過時時間長,可能存在安全風險,須要在註銷登陸時清除全部cookies。
private void removeCookie(Context context) {
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
CookieSyncManager.getInstance().sync();
}
還能夠修改指定cookie,刪除緩存,參考如下連接:
http://blog.csdn.net/shichaosong/article/details/7949580
==================
##Android 清除WebView緩存
最近項目中須要用WebView顯示內容,須要使用JavaScript去交互,可是每次加載都加載到了緩存的數據,這裏記錄一下如何去清除WebView緩存。
首先要了解一些感念。
WebView的緩存能夠分爲頁面緩存和數據緩存.
####頁面緩存 : >指加載一個網頁時的html、JS、CSS等頁面或者資源數據。 >這些緩存資源是因爲瀏覽器的行爲而產生,開發者只能經過配置HTTP響應頭影響瀏覽器的行爲才能間接地影響到這些緩存數據。 >緩存的索引存放在/data/data/package_name/databases下。 >文件存放在/data/data/package_name/cache/xxxwebviewcachexxx下。
####數據緩存 : >數據緩存分爲AppCache和DOM Storage兩種。 >這些緩存資源是由開發者的直接行爲而產生,全部的緩存數據都由開發者直接徹底地掌控。 >Android中Webkit使用一個db文件來保存AppCache數據(my_path/ApplicationCache.db) >Android中Webkit會爲DOM Storage產生兩個文件(my_path/localstorage/http_h5.m.taobao.com_0.localstorage和my_path/localstorage/Databases.db)。
具體能夠參考Url……
####清理WebView緩存
1.webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); 2.context.deleteDatabase(「WebView.db」); 3.context.deleteDatabase(「WebViewCache.db」); 4.webView.clearCache(true); 5.webView.clearHistory(); 6.webView.clearFormData(); 7.getCacheDir().delete(); 8.用File的delete方法刪除緩存文件夾;
PS:老實說,對個人問題,沒多大用,仍是那句話,有事請Google…
其實若是你只是想要每次用webView.loadUrl(url)加載新的頁面顯示,那麼調用webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE)就能夠實現了,並不須要去刪除緩存文件什麼的。
可是個人項目中使用了JavaScript的交互,而JavaScript的加載是經過頭文件去獲取加載的,因此每次我去獲取新的頁面的時候,雖然頁面是新的,可是頭文件中的數據仍是old的,因此每次加載到的js都是old的。那麼如何去作呢?
上面提到這個頭文件是瀏覽器HTTP相應頭去獲取的,開發者只能間接的影響,並不能控制。
因此單獨的webView.clearCache(true)是不能成功的,還須要清除webView的Cookie才行。
因此我最終的解決方法是在Activity的onDestroy()方法中添加以下代碼:
@Override
protected void onDestroy() {
super.onDestroy();
//清空全部Cookie
CookieSyncManager.createInstance(QzmobileApp.getContext()); //Create a singleton CookieSyncManager within a context
CookieManager cookieManager = CookieManager.getInstance(); // the singleton CookieManager instance
cookieManager.removeAllCookie();// Removes all cookies.
CookieSyncManager.getInstance().sync(); // forces sync manager to sync now
webView.setWebChromeClient(null);
webView.setWebViewClient(null);
webView.getSettings().setJavaScriptEnabled(false);
webView.clearCache(true);
}
CookieSyncManager已經@Deprecated,可是requires API level 21,因此……
PS:其實最好是把清除緩存的代碼都封裝到一個類,而後調用靜態方法便可。
==============
在Android應用程序中常常會加載一個WebView頁,若是須要客戶端向WebView傳遞信息,好比Cookie,也是能夠的。
須要應用程序先將Cookie注入進去,打開該網頁時,WebView會將加載的url經過http請求傳輸到服務器。同時,在此次請求中,會將Cookie信息經過http header傳遞過去。
流程以下:
一、客戶端經過如下代碼設置cookie
public static void synCookies(Context context, String url) {
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setCookie(url, "uid=1243432");
CookieSyncManager.getInstance().sync();
}
二、CookieManager會將這個Cookie存入該應用程序/data/data/databases/目錄下的webviewCookiesChromium.db數據庫的cookies表中
三、打開網頁,WebView從數據庫中讀取該cookie值,放到http請求的頭部,傳遞到服務器
四、客戶端能夠在註銷登陸時清除該應用程序用到的全部cookies
private void removeCookie(Context context) {
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
CookieSyncManager.getInstance().sync();
}
==============
1.It does however, get called when the WebView to load a different URL from the one the user had requested.
2.Calling loadUrl() will also trigger the shouldOverrideUrlLoading() method. (Only when a new url is about to be loaded.)
Give the host application a chance to take over the control when a new url is about to be loaded in the current WebView. If WebViewClient is not provided, by default WebView will ask Activity Manager to choose the proper handler for the url. If WebViewClient is provided, return true means the host application handles the url, while return false means the current WebView handles the url.
Ref : public boolean shouldOverrideUrlLoading (WebView view, String url)
===========
Use
getOriginalUrl ()
It returns the URL that was originally requested for the current page
getUrl () is not always the same as the URL passed to WebViewClient.onPageStarted because although the load for that URL has begun, the current page may not have changed.
getOriginalUrl () gets the original URL for the current page. This is not always the same as the URL passed to WebViewClient.onPageStarted because although the load for that URL has begun, the current page may not have changed. Also, there may have been redirects resulting in a different URL to that originally requested.