Android 中的奇怪(无效?)堆栈跟踪?
这可能更多是出于好奇心,而不是解决问题的愿望,因为它看起来是随机发生的,而且只发生过一次。然而,也许它可以让我们了解 java 或 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 库进行过单一引用,该帮助程序只负责对自定义视图进行一些测量。这让我觉得这是 Dalvik VM 中的一个错误或者其他什么。
顺便说一句,该应用程序像往常一样在 Eclipse 中构建。
是的,按钮上的文本不是来自 lightstreamer 提供的值,我可以保证这一点。
This is probably more about curiosity, not the wish to fix a problem, because it occurred seemingly randomly and only once. However, perhaps it may shed some light on some obscure aspects of java or android.
We use the Lightstreamer library, and in essence it's a streaming library, for which we register a simple listener which gets called whenever the streaming provides new values.
I've encountered an exception in my application, and inspected the stacktrace in logcat. I cannot figure out what's going on there. Here is the (relevant) top of the trace:
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)
And here is ShrinkingTextViewHelper.java
in its entirety:
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);
}
}
}
This is the ButtonEx
class which is also present in the stacktrace:
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;
}
}
As you might guess, there is no, nor has ever been, a single reference to the lightstreamer library in a helper which is just responsible for some measuring of custom views. Which makes me think this is a bug in the Dalvik VM or something.
BTW, the application was built as usual, in Eclipse.
And yes, the text on the button does not come from lightstreamer-provided values, I can guarantee that.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
查看正确的文件/类:-)
异常来自于
com.ourapp.view
中的ShrinkingTextViewHelper
类,而发布的类位于com.ourapp< /代码>。
快乐编码。
Look at the correct file/class :-)
The exception comes from the class
ShrinkingTextViewHelper
incom.ourapp.view
while the class posted lives incom.ourapp
.Happy coding.