Android:声明静态位图?是还是不是?

时间:2013-02-12 00:31:27

标签: android static bitmap declaration

有人最近评论了我的代码,我声明了以下内容:

private Bitmap splashBackground;
private Bitmap lightDot;
private static Bitmap scaledBackground;
private static Bitmap scaledLightDot;

他们建议我不要声明正确的位图。

但是,我已经尝试了所有内容,除非我将它们声明为静态,否则我的代码无效。

此外,“公共静态Bitmap createScaledBitmap(Bitmap src,int dstWidth,int dstHeight,boolean filter)”似乎出现在官方的Android开发者网站上,所以我对我应该做什么和不该做什么感到有点困惑

任何指针都将不胜感激 - 谢谢

编辑:澄清:

当我从声明中删除静态时,到我的onDraw()方法时,缩放的位图为空。 (我在initialise()方法中创建缩放的位图对象,一旦创建它,​​它是有效的(即,不为空) - 但是在onDraw中似乎变为null,除非我将其声明为静态。

我从我的活动类调用了我的initialise()方法。

编辑:根据要求提供更多代码。

我的OnCreate方法:正如您所看到的,我正在通过我的屏幕高度和宽度,因此我可以创建我的缩放位图

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        displaySplashScreen= new SplashScreen(this);

        requestWindowFeature(Window.FEATURE_NO_TITLE);

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        // set View
        setContentView(new SplashScreen(this));
        WindowManager w = getWindowManager();   
        Display d = w.getDefaultDisplay();
        int width=d.getWidth();
        int height=d.getHeight();
        displaySplashScreen.initialise(width, height);
}

我的初学方法:

 public void initialise(int w, int h)
 {       
     //Get width and height (passed in from Activity)

     vwidth=w;
     vheight=h;

     //Create pre-scaled bitmaps

    scaledBackground = Bitmap.createScaledBitmap(splashBackground,  vwidth, vheight, true);
    scaledLightDot = Bitmap.createScaledBitmap(lightDot, vwidth, vheight, true);

 }

我还可以补充说,如果我以相同的方式使用标准变量(比如int number;)并将其设置为initalise(number = 5;),那么number在初始化方法中仅等于5。如果我从onDraw()记录它,它将一直重复返回'0'!这令人费解。

感谢大家到目前为止,如果需要更多代码,请告诉我......

4 个答案:

答案 0 :(得分:1)

一般来说,将static用于Bitmap是一个非常糟糕的主意。这有很多很好的理由,主要是避免内存泄漏。

  

此外,“公共静态Bitmap createScaledBitmap(Bitmap src,int dstWidth,int dstHeight,boolean filter)”似乎出现在官方Android开发者网站上......

这不是static Bitmap。这是对类方法的方法调用。静态不起作用,返回类型(Bitmap)不是静态的。这意味着该方法是静态的,不需要调用实例。它将返回一个位图,放置在您选择的适当变量中。

  

我从我的活动类调用我的initialise()方法。

这句话非常无益。来自在哪个类中被调用?它位于onCreate()onStart()onResume(),还有其他一些自定义方法吗?你选择做某些事情的地点和时间会对他们的成功产生巨大影响。

  

...但是在onDraw中似乎变为null,除非我将其声明为静态。

这可能有几个原因,因为我们没有任何代码,所以确实没有合格的答案。以下是一些需要注意的事项。

  • 这可能是因为活动正在重新创建。
  • 这也可能是因为某些似乎无关的方法实际上被调用了。这可能是您手动将其设置为null的地方。
  • 这可能是由于createScaledBitmap()方法使用不当造成的。
  • 由于内存不足,Bitmap可能会被回收(这实际上比人们想象的更频繁)

编辑:审核您的代码后

这看起来可能是罪魁祸首。上面,你有......

displaySplashScreen= new SplashScreen(this);

在下面,您添加...

setContentView(new SplashScreen(this));

这意味着您正在创建 两个 Splashscreens。当您不使用static时获得空指针的一个原因可能是因为您使用的线路更远......

displaySplashScreen.initialise(width, height);

但是,由于您的contentView设置为 SplashScreen,因此您实际上并未使用该视图。要解决此问题,请确保您正在与 相同的 视图对象进行通信。即。

setContentView(displaySplashScreen);

这至少可以确保您查看同一个对象。您可能需要重新组织一下,具体取决于发生的其他事情。例如,

setContentView(displaySplashScreen);

......可能必须出现在......下面

 displaySplashScreen.initialise(width, height);

这是你可能不得不玩的东西,但我没有看到任何其他任何其他立即指示。请注意,首先解析nullpointerexceptions通常会导致代码中出现更多错误。坚持下去,按顺序解决每个问题。

答案 1 :(得分:1)

这一行错了:

    // set View
    setContentView(new SplashScreen(this));        // This line is wrong.

应该是这样的:

    // set View
    setContentView(displaySplashScreen);        // displaySplashScreen is created earlier.

您创建了SplashScreen的两个实例。你应该继续使用相同的实例。

答案 2 :(得分:0)

我投票赞成, 这个是静态变量

private Bitmap splashBackground;
private Bitmap lightDot;
private static Bitmap scaledBackground;
private static Bitmap scaledLightDot;

这个是静态方法

public static Bitmap createScaledBitmap (Bitmap src, 
     int dstWidth, int dstHeight, boolean filter)

静态变量通常是为常量声明的,如果你有一个类,变量属于class而不是对象

public class car {
      private static colorOfCar;
      private numberOfDoor;
}

假设你有一辆轿车并且有2个变量colorOfCar和numberOfDoor当你从汽车类创建一个对象保时捷和法拉利如果你改变门的数量就可以了,你的保时捷对象和法拉利对象中的numberOfDoor会有所不同,但是如果你改变了colorOfCar,那么保时捷对象和法拉利对象colorOfCar都会被改变,因为colorOfCar是属于类而不是对象的静态对象。

我希望你理解我的解释。如果您找到我的答案帮助您,请投票并接受我的答案,如果您有任何其他问题,请随时在评论中提问,谢谢:)

答案 3 :(得分:0)

如果没有您的代码,您似乎正在使用您的视图不止一次创建。也许在视图的两个实例中,或者可能重新创建相同的视图(活动重启)。在第一次出现时,在onDraw()之前调用initialize(),使您的静态Drawable初始化并有效。第二次,onDraw()在 initialize()之前运行(当Drawable是静态时它起作用)。这很可能是由于您对视图进行了膨胀并且之后调用了initialize()(这意味着视图已经在布局中)。即。

public void onCreate(Bundle savedInstanceState) {
  setContentView(R.layout.mylayout); //the view is added to layout, onDraw() may be called
  MyView view = (MyView)findViewById(R.id.myview);
  view.initialize();  //initializing the drawable from null
  //no guarentee that initialize was called before onDraw()
}

当Drawable是静态的时,这运行正常,因为在绘制第二个视图时,它使用的是由第一个视图初始化的相同的Drawable 。删除静态时,需要确保在onDraw()之前始终调用initialize。

不是从您的活动中调用initialize(),而是为什么不从View的构造函数中调用它?我经常使用以下模式:

public class MyView extends View {

  private Bitmap splashBackground;
  private Bitmap lightDot;
  private Bitmap scaledBackground;
  private Bitmap scaledLightDot;

  public MyView(Context context) {
    super(context);
    init();
  }

  public MyView(AttributeSet attr, Context context) {
    super(attr, context);
    //parse attr for xml attributes
    init();
  }

  private void init() {
    splashBackground = getResources().getDrawable(R.drawable.splash_background);
    lightDot = getResources().getDrawable(R.drawable.light_dot);
    scaledLightDot = Bitmap.createScaledBitmap(lightDot, getDPI(32), getDPI(32), false);
  }

  public void onSizeChanged(int width, int height) {
    scaledBackground =  Bitmap.createScaledBitmap (splashBackground, width, height, false);
  }

  /**
   * Convert pixel value to device independent pixels (DPI)
   * @params pixels  Value for pixel size for MDPI screens
   */
  private int getDPI(int pixels) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, pixels, getResources().getDisplayMetrics());
  }

  public void onDraw(Canvas canvas) {
    //non-static drawables are guaranteed to be not-null
    canvas.draw(scaledBackground, 0, 0, null);
    canvas.draw(scaledLightDot, 10, 10, null);
  }
}

你将全力以赴