3

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

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

他们建议我不要声明 satic 位图。

但是,我已经尝试了所有方法,除非我将它们声明为静态,否则我的代码不起作用。

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

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

编辑:澄清:

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

我正在从我的活动类中调用我的 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

4 回答 4

1

这一行是错误的:

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

应该是这样的:

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

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

于 2013-02-12T03:55:44.500 回答
1

一般来说,使用staticfor Bitmaps 是一个非常糟糕的主意。这有很多很好的理由,主要与避免内存泄漏有关。

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

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

initialise()从我的活动课程中调用我的方法。

这种说法是非常无益的。从课堂上的哪个位置调用它?它在onCreate(), onStart(), onResume(), 其他一些自定义方法中吗?您选择在何时何地做某些事情会对它们的成功程度产生巨大影响。

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

这可能有几个可能的原因,并且由于我们没有您的任何代码,因此确实没有合格的答案。这里有一些事情要看。

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

编辑:查看您的代码后

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

displaySplashScreen= new SplashScreen(this);

下面,您添加...

setContentView(new SplashScreen(this));

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

displaySplashScreen.initialise(width, height);

但是由于您的 contentView 设置为的SplashScreen,因此您实际上并没有使用该视图。要解决此问题,请确保您正在与同一个视图对象交谈。IE

setContentView(displaySplashScreen);

这至少可以确保您看到的是同一个对象。根据正在发生的其他事情,您可能需要重新组织一下。例如,

setContentView(displaySplashScreen);

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

 displaySplashScreen.initialise(width, height);

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

于 2013-02-12T02:39:45.857 回答
0

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

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(),不如从视图的构造函数中调用它?我经常使用以下模式:

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);
  }
}

你会准备好的

于 2013-02-12T03:22:17.407 回答
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)

静态变量通常声明为常量,如果您有一个类,则该变量属于类而不是对象

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

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

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

于 2013-02-12T01:10:25.033 回答