這可能更多的是好奇心,而不是解決問題的願望,因爲它似乎是隨機發生的,只有一次。不過,也許它可能會讓我們對java或android的一些模糊的方面有所瞭解。奇怪(無效?)stacktrace在android中?
我們使用Lightstreamer庫,本質上它是一個流式庫,爲此我們註冊一個簡單的監聽器,只要流提供新值,就會調用該監聽器。
我在應用程序中遇到了異常,並檢查了logcat中的堆棧跟蹤。我無法弄清楚那裏發生了什麼。這裏是微量的(相關)頂部:
11-25 15:06:50.770 E/AndroidRuntime(3100): FATAL EXCEPTION: main
11-25 15:06:50.770 E/AndroidRuntime(3100): java.lang.NullPointerException
11-25 15:06:50.770 E/AndroidRuntime(3100): at com.lightstreamer.ls_client.UpdateInfoImpl.getNewValue(UpdateInfoImpl.java:142)
11-25 15:06:50.770 E/AndroidRuntime(3100): at com.ourapp.view.ShrinkingTextViewHelper.onMeasure(ShrinkingTextViewHelper.java:30)
11-25 15:06:50.770 E/AndroidRuntime(3100): at com.ourapp.view.ButtonEx.onMeasure(ButtonEx.java:67)
11-25 15:06:50.770 E/AndroidRuntime(3100): at android.view.View.measure(View.java:10828)
這裏是在其整體ShrinkingTextViewHelper.java
:
package com.ourapp.view;
import android.text.TextPaint;
import android.text.TextUtils.TruncateAt;
/**
* Check text size on view and change the text size if it's width not fit to control's width
*
*/
public class ShrinkingTextViewHelper {
public static void onMeasure(ShrinkingTextView view, int widthMeasureSpec, int heightMeasureSpec) {
CharSequence text = view.getText();
view.onMeasureSuper(widthMeasureSpec, heightMeasureSpec);
TextPaint paint = view.getPaint();
float paddings = view.getPaddingLeft() + view.getPaddingRight();
paint.setTextSize(view.getInitialTextSize());
float size = paint.getTextSize();
while (size >= view.getMinTextSize()
&& paddings + paint.measureText(text, 0, text.length()) > view.getMeasuredTextWidth()
&& (view.getLineCount() == 1 || view.getLineCount() > view.getMaxLines())) {
paint.setTextSize(--size);
view.setText(text);
view.onMeasureSuper(widthMeasureSpec, heightMeasureSpec);
}
line 30:if (paddings + paint.measureText(text, 0, text.length()) > view.getMeasuredTextWidth()) {
view.setEllipsize(TruncateAt.END);
}
}
}
這是ButtonEx
類也存在於堆棧跟蹤:
package com.ourapp.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.method.SingleLineTransformationMethod;
import android.util.AttributeSet;
import android.widget.Button;
import com.ourapp.R;
/**
* Extended button class. It could shrink text on the face.
*
*/
public class ButtonEx extends Button implements ShrinkingTextView {
private static final float DEFAULT_MIN_TEXT_SIZE_DP = 10;
private float minTextSizePx;
private float initialTextSize;
private int maxLines;
/**
* Class constructor
* @param context
* @param attrs
*/
public ButtonEx(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray t = getContext().obtainStyledAttributes(attrs, R.styleable.ButtonEx);
minTextSizePx = t.getDimension(R.styleable.ButtonEx_minTextSize, dipToPixels(DEFAULT_MIN_TEXT_SIZE_DP));
t.recycle();
int att[] = new int[] { android.R.attr.singleLine };
t = getContext().obtainStyledAttributes(attrs, att);
boolean singleLine = t.getBoolean(0, true);
boolean hasSingleLine = t.hasValue(0);
t.recycle();
att = new int[] { android.R.attr.maxLines };
t = getContext().obtainStyledAttributes(attrs, att);
boolean hasMaxLines = t.hasValue(0);
if (singleLine && hasSingleLine) {
maxLines = 1;
} else {
maxLines = t.getInteger(0, 1);
}
if (singleLine && hasSingleLine
|| !hasSingleLine && !hasMaxLines) {
setTransformationMethod(new SingleLineTransformationMethod());
}
setMaxLines(maxLines);
t.recycle();
att = new int[] { android.R.attr.textSize };
t = getContext().obtainStyledAttributes(attrs, att);
initialTextSize = t.getDimension(0, 0);
t.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
ShrinkingTextViewHelper.onMeasure(this, widthMeasureSpec, heightMeasureSpec);
}
private float dipToPixels(float dip) {
return dip * getContext().getResources().getDisplayMetrics().density;
}
/**
* Get min size of text on title.
*/
public float getMinTextSize() {
return minTextSizePx;
}
/**
* Called to determine the size requirements for this view and all of its children.
*/
public void onMeasureSuper(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* Get text width
*/
public int getMeasuredTextWidth() {
return getMeasuredWidth();
}
/**
* Get max lines number. It parsed from XML attributes. Default value is 1.
*/
public int getMaxLines() {
return maxLines;
}
@Override
protected void onTextChanged(CharSequence text, int start, int before,
int after) {
super.onTextChanged(text, start, before, after);
requestLayout();
}
/**
* Get initial text size.
*/
public float getInitialTextSize() {
return initialTextSize;
}
}
正如你可能猜到的那樣,在助手中沒有,也沒有曾經有過一個關於lightstreamer庫的單一引用,它只負責一些測量cust om意見。這使我認爲這是Dalvik VM中的一個錯誤。
順便說一句,該應用程序是像往常一樣在Eclipse中構建的。
是的,按鈕上的文字確實是而不是來自lightstreamer提供的值,我可以保證。
它又是什麼奇怪/無效?很明顯,從'onMeasure'調用'getNewValue'方法中有一個NPE。如果沒有調用它,那麼它永遠不會被執行來生成所述異常(和堆棧跟蹤)。 – 2011-11-29 09:04:35
這是沒有跡象表明'onNeasureValue'onMeasure' –
我真的*懷疑:這種「缺陷」會使Dalvik虛擬機的功能失效。粘貼整個'onMeasure'方法? – 2011-11-29 09:06:29