我正在android中创建一个小型的musicplayer应用程序,其中我的主要活动是使用许多这样的静态变量: -
public class Fragmentactivity extends FragmentActivity {
static ArrayList<String> s3=new ArrayList<String>();
static ArrayList<String> s5=new ArrayList<String>();
static ArrayList<String> songpaths=new ArrayList<String>();
static ArrayList<String> alldirectorypaths=new ArrayList<String>();
static ArrayList<String> internalpaths=new ArrayList<String>();
static ArrayList<String> tempsongnames=new ArrayList<String>();
static ArrayList<Bitmap> thumbnails=new ArrayList<Bitmap>();
static int internal=0;
static ArrayList<String> folderpaths=new ArrayList<String>();
//my addtional code after it
}
我正在其他课程中访问它,如: -
public class A{
Fragmentactivity.songpaths.get(index);
//and in many other classes also i used it
我在大多数课程中到处都有很多静态变量 但现在我了解到这不是开发的好习惯。
我应该继续使用静态还是应该使用getter / setter?
或者,如果有其他方法可以重复使用变量......请建议我。
任何帮助将不胜感激:)
提前致谢:)
答案 0 :(得分:8)
我不是Android专家。 static具有特殊含义,可以在所有实例之间共享它们。
因此,如果你打算在它们的多个实例之间分享它们,那就用当前的方式进行预测。
我应该继续使用静态还是应该使用getter / setter?
假设您想要共享变量,我会将它们混合
Fragmentactivity.getSongNames().get(index);
更新:
如果你没有对它进行多次讨论,只需摆脱静态并为其提供getter和setter。这就是你所需要的一切。
public class Fragmentactivity extends FragmentActivity {
private ArrayList<String> s3=new ArrayList<String>();
...
...
public ArrayList<String> getS3() {
return this.s3;
}
public setS3(ArrayList<String> input){
this.s3= input;
}
...
答案 1 :(得分:4)
在数据模型的设计中(在使用静态访问变量的上下文中)要回答的主要问题是 - 此变量是否与类相关联(如果是这样,那么我们使用static modifier)或者使用这个类的具体实例(然后这个变量应该是非静态的)。
以下是关于在Java中使用静态变量的优点和缺点的大量帖子(link1,link2,link3)。此信息也与Android相关。还有一些事情需要在Android上提及:
关于静态访问数据的可能替代方案,以下是最常用的方法:
单身人士模式。最简单的方法之一(来自通常的Java):
public class GlobalStorage {
private static volatile GlobalStorage instance; // and drumroll - here we use static access again to make this data accessible everywhere in the app
private GlobalStorage() { }
public static GlobalStorage getInstance() {
if (instance == null ) {
synchronized (GlobalStorage.class) {
if (instance == null) {
instance = new GlobalStorage();
}
}
}
return instance;
}
}
Application类的用法。
创建一个子类Application
:
public class CustomApp extends Application{
private Storage mStorage;
@Override
public void onCreate() {
super.onCreate();
mStorage = new Storage();
}
public Storage getStorage(){
return this.mStorage;
}
}
并将其作为<application>
标记的属性
<application
android:name=".CustomApp"
.... />
虽然这种方法是框架定义的,但它也不是“银弹”。直接从documentation:
通常不需要子类Application。在大多数情况下, 静态单例可以在更模块化的情况下提供相同的功能 办法。如果您的单身人士需要全局上下文(例如注册 广播接收器),可以给出一个检索它的功能 内部使用Context.getApplicationContext()的Context 首先构建单身人士。
答案 2 :(得分:3)
如果您想要传达2个碎片/活动,请使用Bundle
答案 3 :(得分:3)
它或多或少取决于您希望实现的功能。就像你想要在实例之间共享这些变量一样。使用getter setters
与声明变量static
无关。对于任何类型的变量,您都可以使用getters and setters
。
除了访问者/变异者之外,他们还有其他优势。
通常声明getter会阻止你的变量(esp
mutable
)暴露给外部世界。如果您不希望您的客户直接更新您的变量,那么Setter会很有帮助。
例如,考虑日期变量的情况
对于
date
类型变量,您可能希望将日期变量的副本返回给客户端,而不是您自己的引用。因为客户端可能会滥用此引用或损坏它。 在调用setter时,您可能希望先检查日期或其格式的有效性。
答案 4 :(得分:3)
我看到你正在尝试使用静态变量,因为songpaths,alldirectorypaths,internalpaths ..可能是只应存在于应用程序中访问的一个实例中的值。 你需要的是使用单例模式。
单例模式是一种设计模式,它将类的实例化限制为一个对象。当需要一个对象来协调整个系统的操作时,这非常有用。 (维基百科)
根据Joshua Bloch的“Effective Java”一书,实现单例的最有效方法是使用Enums。
public enum MusicPlayerContext{
INSTANCE;
public List<String> internalpaths = new ArrayList<String>();
public List<String> alldirectorypaths= new ArrayList<String>();
}
public class MyActivity extends Activity{
public void doSomething(){
List<String> intPaths = MusicPlayerContext.INSTANCE.internalpaths;
}
}
还有一件事..更喜欢使用接口进行变量声明(List)而不是实现(ArrayList&lt; String&gt;)
答案 5 :(得分:3)
static
是线程不安全的,如果您不想使用get()/ set()函数,则可以使用public
来修改基本数据类型。
像这样定义点:
public class Point{
public double x;
public double y;
}
然后像这样使用Point:
Point p = new Point();
p.x = ;
p.y = ;
但是,对于Object数据类型,最好使用get()/ set()函数,它们是安全的。
答案 6 :(得分:3)
这个问题已经回答here。
我个人会使用Singleton Pattern,它非常容易实现,使您的代码更容易测试,将来更容易更改。
关键是,对于静态变量,您必须在客户端的任何地方编写arguments
,并将客户端耦合到此特定类。
使用单身人士,你可以,f.i。,介绍一个界面,然后将来很容易用另一个替换单身人士。
Singleton实现也允许延迟初始化。
答案 7 :(得分:3)
在像C ++这样的本地语言中,使用getter(i = getCount())而不是直接访问字段(i = mCount)是常见做法。这是C ++的一个很好的习惯,并且经常用于其他面向对象的语言,如C#和Java,因为编译器通常可以内联访问,如果您需要限制或调试字段访问,您可以随时添加代码。 / p>
然而,这在Android上是一个坏主意。虚拟方法调用比实例字段查找要昂贵得多。遵循常见的面向对象编程实践并在公共接口中使用getter和setter是合理的,但在类中,您应该始终直接访问字段。
因此,作为Android开发人员指南,您应该避免使用getter / setter()。
参考:http://developer.android.com/training/articles/perf-tips.html
答案 8 :(得分:2)
对于上下文,让我们简单地谈谈static
的作用。 static
是一个关键字,它将变量的范围更改为全局,在所有实例中保持其值,并在应用程序的生命周期内永久分配内存。
这有一些后果:
为了更好地执行您使用static
完成的工作,我们可以使用interface
。
制作新的interface
:
public interface FragmentActivityInterface {
String getSongPath(int index);
//etc...
}
让Fragment
实施interface
:
public class Fragmentactivity extends FragmentActivity implements FragmentActivityInterface {
static ArrayList<String> s3=new ArrayList<String>();
static ArrayList<String> s5=new ArrayList<String>();
static ArrayList<String> songpaths=new ArrayList<String>();
static ArrayList<String> alldirectorypaths=new ArrayList<String>();
static ArrayList<String> internalpaths=new ArrayList<String>();
static ArrayList<String> tempsongnames=new ArrayList<String>();
static ArrayList<Bitmap> thumbnails=new ArrayList<Bitmap>();
static int internal=0;
static ArrayList<String> folderpaths=new ArrayList<String>();
//my addtional code after it
@Override
public String getSongPath(int index) {
return songpaths.get(index);
}
//etc...
}
让您的其他课程需要FragmentActivityInterface
:
public class A {
private FragmentActivityInterface fragInterface;
public A (FragmentActivityInterface fragInterface) {
this.fragInterface = fragInterface;
}
}
最后,当您创建A
课程的实例时,您只需传入您的活动。
A foo = new A(this);
现在,在A
您想要访问FragmentActivity
成员的任何地方,只需使用fragInterface.getSongPath(0)
。