|
楼主 |
发表于 2016-4-25 16:34:34
|
显示全部楼层
终于翻译完了,我只能说,我真的不会翻译……我也没看懂……
How to declare global variables in Android?
http://stackoverflow.com/questio ... ariables-in-android
I wrote this answer back in '09 when Android was relatively new, and there were many not well established areas in Android development. I have added a long addendum at the bottom of this post, addressing some criticism, and detailing a philosophical disagreement I have with the use of Singletons rather than subclassing Application. Read it at your own risk.
我写这个答案是在09年,那时安卓还是相对较新的,安卓开发中很中地方制定的都还不是很好。我在这条回复的底部添加了一段长长的附录,解决了一些批评,并且详细说明了有关使用单例比Application的子类更好的哲学分歧。说读时请自己承担风险。
ORIGINAL ANSWER:
The more general problem you are encountering is how to save state across several Activities and all parts of your application. A static variable (for instance, a singleton) is a common Java way of achieving this. I have found however, that a more elegant way in Android is to associate your state with the Application context.
原始签案:
通常你可能会遇到这个问题:怎么在多个activity以有你应用中的每个地方保存状态,在java中可以使用一个静态变量(比如单例)来完成这个需求。然而,我发现在安卓中一个更优雅(简洁)的方式是将状态与Application context相关联。
As you know, each Activity is also a Context, which is information about its execution environment in the broadest sense. Your application also has a context, and Android guarantees that it will exist as a single instance across your application.
大家知道,每个activity也是一个context,在广泛意义上它是关于运行环境的信息。你的应用也有一个context,并表安卓保证它在应用中是一个单例的。
The way to do this is to create your own subclass of android.app.Application, and then specify that class in the application tag in your manifest. Now Android will automatically create an instance of that class and make it available for your entire application. You can access it from any context using the Context.getApplicationContext() method (Activity also provides a method getApplication() which has the exact same effect). Following is an extremely simplified example, with caveats to follow:
完成这个,需要创建自己的Application的子类,并且在manifest用application标签申明这个类。然后安卓将会自动创建这个类的一个实例并且对你的整个应用可用。你可以在任何context中用Context.getApplicationContext()这个方法来使用它,(Activity也提供一个getApplication()的方法有相同的效果)。下面是一个很简单的例子和说明:
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
This has essentially the same effect as using a static variable or singleton, but integrates quite well into the existing Android framework. Note that this will not work across processes (should your app be one of the rare ones that has multiple processes).
这本质上和使用一个静态的变量或单例有相同的效果,但和已存在的安卓框架结合的更好。注意这在跨进程中将不工作(你的app应该极少使用多进程)。
Something to note from the example above; suppose we had instead done something like:
上面例子中的注意,假设我们要做下面的事:
class MyApp extends Application {
private String myState = /* complicated and slow initialization */;
public String getState(){
return myState;
}
}
Now this slow initialization (such as hitting disk, hitting network, anything blocking, etc) will be performed every time Application is instantiated! You may think, well, this is only once for the process and I'll have to pay the cost anyways, right? For instance, as Dianne Hackborn mentions below, it is entirely possible for your process to be instantiated -just- to handle a background broadcast event. If your broadcast processing has no need for this state you have potentially just done a whole series of complicated and slow operations for nothing. Lazy instantiation is the name of the game here. The following is a slightly more complicated way of using Application which makes more sense for anything but the simplest of uses:
现在缓慢的初始化(比如接入硬盘、接入网络、有什么阻塞了等等(这里不会翻译))将在每一次应用初始化时被执行!你可能会想,对进程来说只会执行一次,反正都要消耗,对吗?比如,如Dianne Hackborn在下面提到的,你的进程完全有可能因为一个后台广播而初始化。如果你的广播进程不需要这个状态,那么你可能做了一系列复杂、缓慢的操作,但并没有什么用。延迟实例就是这个游戏的名字。下面是一个稍微复杂点的方法来使用Application,更有意义,但用法很简单(不会翻译)。
class MyApp extends Application {
private MyStateManager myStateManager = new MyStateManager();
public MyStateManager getStateManager(){
return myStateManager ;
}
}
class MyStateManager {
MyStateManager() {
/* this should be fast */
}
String getState() {
/* if necessary, perform blocking calls here */
/* make sure to deal with any multithreading/synchronicity issues */
...
return state;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
String state = stateManager.getState();
...
}
}
While I prefer Application subclassing to using singletons here as the more elegant solution, I would rather developers use singletons if really necessary over not thinking at all through the performance and multithreading implications of associating state with the Application subclass.
我认为Application的子类来使用单例是一个更优雅的解决方案,我希望开发者们使用和Application的子类关联的单例如果有必要,而不考虑性能和多线程对关联状态的影响(不会翻译)。
NOTE 1: Also as anticafe commented, in order to correctly tie your Application override to your application a tag is necessary in the manifest file. Again, see the Android docs for more info. An example:
注意 1:同样作为反对的评论,为了和你的应用关联,你必须在manifest中重写application标签,另外,可以查看安卓文档来了解更多信息。比如:
<application
android:name="my.application.MyApp"
android:icon="..."
android:label="...">
</application>
NOTE 2: user608578 asks below how this works with managing native object lifecycles. I am not up to speed on using native code with Android in the slightest, and I am not qualified to answer how that would interact with my solution. If someone does have an answer to this, I am willing to credit them and put the information in this post for maximum visibility.
注意2:user608578在下面问说,怎么样管理native对象的生命周期,我没有在安卓上使用过native code,所以我也没有资格回答那会和我的答案有什么影响。如果有人有这个问题的答案,我很乐意重新编辑这条回复把答案放上。
ADDENDUM:
As some people have noted, this is not a solution for persistent state, something I perhaps should have emphasized more in the original answer. I.e. this is not meant to be a solution for saving user or other information that is meant to be persisted across application lifetimes. Thus, I consider most criticism below related to Applications being killed at any time, etc..., moot, as anything that ever needed to be persisted to disk should not be stored through an Application subclass. It is meant to be a solution for storing temporary, easily re-creatable application state (whether a user is logged in for example) and components which are single instance (application network manager for example) (NOT singleton!) in nature.
附录:
有人提到,这不是持处状态的解决方案,有些东西我可能要在原始答案中更强调些。也就是,它并不是一个好的方案来保存用户或都其他一些需要在应用的生命周期中长期保存的信息。因此,我考虑到下面的很多评论都和应用被杀死等想关,所以需要在硬盘中持久化的东西就不就该用Application的子类来存储。实际上,它是一个方案来保存临时变量、易于重建的应用状态(比如用户是否登录)以及单例的组件(比如应用的网络管理)(不是单例模式)。
Dayerman has been kind enough to point out an interesting conversation with Reto Meier and Dianne Hackborn in which use of Application subclasses is discouraged in favor of Singleton patterns. Somatik also pointed out something of this nature earlier, although I didn't see it at the time. Because of Reto and Dianne's roles in maintaining the Android platform, I cannot in good faith recommend ignoring their advice. What they say, goes. I do wish to disagree with the opinions, expressed with regards to preferring Singleton over Application subclasses. In my disagreement I will be making use of concepts best explained in this StackExchange explanation of the Singleton design pattern, so that I do not have to define terms in this answer. I highly encourage skimming the link before continuing.
Dayerman很好心的指出了Reto Meier和Dianne Hackborn关于单例模式不推荐使用Application的子类的有趣的对话。Somatik同样在早期我还没有意识到的时候指出了在nature中的一些问题。因为Reto 和Dianne 在维持安卓平台中的一些作用,我不能完全忽视他们的意见。他们说的继续。(哭了,完全不会翻译)我希望不同意这个观点,表达出单例比Application的子类更好。在我的不同意中,我将用最好的概念在将换解释中来解释单例设计模式。所以我不发给答案下定义,我很鼓励在继续前抛开这个链接。
Point by point:
Dianne states, "There is no reason to subclass from Application. It is no different than making a singleton..." This first claim is incorrect. There are two main reasons for this. 1) The Application class provides a better lifetime guarantee for an application developer; it is guaranteed to have the lifetime of the application. A singleton is not EXPLICITLY tied to the lifetime of the application (although it is effectively). This may be a non-issue for your average application developer, but I would argue this is exactly the type of contract the Android API should be offering, and it provides much more flexibility to the Android system as well, by minimizing the lifetime of associated data. 2) The Application class provides the application developer with a single instance holder for state, which is very different from a Singleton holder of state. For a list of the differences, see the Singleton explanation link above.
一点一点说,
Dianne说,“没有理由用Application的子类,这和用一个单例没有区别”。这第一个声明是不正确的。有两个主要的原因这样做。1)Application类提供一个更好的生命周期保证给开发者;它是保证有应用的生命周期。一个单例并没有明确地和应用的生命周期相关联。(尽管它实际上是关联的。)对于一般的开发者这可能并不重要。但我争论这一点恰好是安卓api应该提供的范围,并且它提供更多的灵活性给安卓系统,来最小化和数据关联的生命周期。2)Application类提供给开发者一个单例来持有状态,它和一个单例来持有状态是完全不一样的。关于不同的列表,见上面单例解释的链接。
Dianne continues, "...just likely to be something you regret in the future as you find your Application object becoming this big tangled mess of what should be independent application logic." This is certainly not incorrect, but this is not a reason for choosing Singleton over Application subclass. None of Diane's arguments provide a reason that using a Singleton is better than an Application subclass, all she attempts to establish is that using a Singleton is no worse than an Application subclass, which I believe is false.
Dianne继续说,你极有可能将来会后悔,因为你发现你的Application对象变得很紊乱,就用逻辑就该独立。这当是不是不正确,但这并不是选择单例而不是Application的子类的原因。Dianne的观点中并没提供一个使用单例比Application的子类更好的原因,所有的她试图确立的是使用一个单例不比Application的子类差,我相信这是不正确的。
She continues, "And this leads more naturally to how you should be managing these things -- initializing them on demand." This ignores the fact that there is no reason you cannot initialize on demand using an Application subclass as well. Again there is no difference.
她继续说,这使得你如何管理这些东西更自然--初始化它们在需要时。这忽视了一个事实,没有原因说你在用用Application的子类时不能在需要时初始化,这里并没有区别。
Dianne ends with "The framework itself has tons and tons of singletons for all the little shared data it maintains for the app, such as caches of loaded resources, pools of objects, etc. It works great." I am not arguing that using Singletons cannot work fine or are not a legitimate alternative. I am arguing that Singletons do not provide as strong a contract with the Android system as using an Application subclass, and further that using Singletons generally points to inflexible design, which is not easily modified, and leads to many problems down the road. IMHO, the strong contract the Android API offers to developer applications is one of the most appealing and pleasing aspects of programming with Android, and helped lead to early developer adoption which drove the Android platform to the success it has today. Suggesting using Singletons is implicitly moving away from a strong API contract, and in my opinion, weakens the Android framework.
Dianne最后说,框架中本来就有很多很多的单例来为应用维护小的共享数据,比如加载资源的缓存,对象池等等,它也工作地很好。我并没争论说使用单例不能工作的很好或都说是一个更好的选择。我只是说,和用Application子类相比,单例并没有提供一个紧密的联系来和安卓系统关联。晚进一步说,使用单例通常表时明不可变的设计,它将不容中易被修改,并在一段时间后带来很多问题。我个人认为,和安卓api提供的application的紧密联系是极好的(不会翻译),并且帮助指引早期的开发者适应驾驭安卓系统……(同不会翻译)。使用单便暗中和API的紧密联系远离了,并且我觉得弱化的安卓框架。
Dianne has commented below as well, mentioning an additional downside to using Application subclasses, they may encourage or make it easier to write less performance code. This is very true, and I have edited this answer to emphasize the importance of considering perf here, and taking the correct approach if you're using Application subclassing. As Dianne states, it is important to remember that your Application class will be instantiated every time your process is loaded (could be multiple times at once if your application runs in multiple processes!) even if the process is only being loaded for a background broadcast event. It is therefore important to use the Application class more as a repository for pointers to shared components of your application rather than as a place to do any processing!
Dianne在下面评论的很好,提到使用Application的子类的一个额外的负面影响是,可能会鼓励或更容易写更少的性能代码。那是正确的,所以我编辑了答案来强调考虑性能的重要性,并且使用正确的方法,如果你正在使用Application的子类。Dianne的观点中,很重要的一点是你要记住你的应用将在每一次进程被加载时初始化(可能同时初始化多次,如果你的应用在多个进程中运行。)甚至当进程仅仅是被后台广播加载时。因此这很重要使用Application类更多地来贮藏应用的共享组件的指针,而不要用来当作执行任何进程的地方。
I leave you with the following list of downsides to Singletons, as stolen from the earlier StackExchange link:
Inability to use abstract or interface classes;
Inability to subclass;
High coupling across the application (difficult to modify);
Difficult to test (can't fake/mock in unit tests);
Difficult to parallelize in the case of mutable state (requires extensive locking);
我从早先的讨论链接中留下下列的单便的负面影响:
不能使用抽像类或接口;
不能使用子类;
和application高耦合(修改困难);
测试困难(不能在单元测试中模拟);
在可变状态下难以维持(请求额外的锁);
and add my own:
Unclear and unmanageable lifetime contract unsuited for Android (or most other) development;
并且加上我自己的:
不清楚和难以管理的生命周期,不适合连接安卓(或都大多数其他的)开发环境; |
|