You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Volley获取JSON后ListView链接点击崩溃:需FLAG_ACTIVITY_NEW_TASK?

我之前也踩过这个坑!问题根源在于:当你在ListView的Item布局里使用android:autoLink="web"时,系统默认的链接跳转逻辑用的是应用级上下文(Application Context),而不是当前Activity的上下文。启动Activity时,非Activity上下文必须加上FLAG_ACTIVITY_NEW_TASK标记,这就导致了崩溃报错。

下面给你两种靠谱的解决方案,都是从「确保用Activity上下文启动Intent」这个核心点出发的:


方案一:自定义TextView重写链接点击逻辑

这种方法适合想保留android:autoLink="web"自动识别链接的场景,只需要替换布局里的TextView为自定义控件:

public class ActivityLinkTextView extends AppCompatTextView {
    public ActivityLinkTextView(Context context) {
        super(context);
        init();
    }

    public ActivityLinkTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ActivityLinkTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        // 启用链接点击能力
        setMovementMethod(LinkMovementMethod.getInstance());
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        // 替换默认的链接点击处理逻辑
        if (getMovementMethod() instanceof LinkMovementMethod) {
            setMovementMethod(new LinkMovementMethod() {
                @Override
                public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        int x = (int) event.getX() - widget.getTotalPaddingLeft() + widget.getScrollX();
                        int y = (int) event.getY() - widget.getTotalPaddingTop() + widget.getScrollY();

                        Layout layout = widget.getLayout();
                        int line = layout.getLineForVertical(y);
                        int offset = layout.getOffsetForHorizontal(line, x);

                        URLSpan[] spans = buffer.getSpans(offset, offset, URLSpan.class);
                        if (spans.length > 0) {
                            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(spans[0].getURL()));
                            // 这里直接用当前TextView的上下文(也就是Activity上下文)启动
                            widget.getContext().startActivity(intent);
                            return true;
                        }
                    }
                    return super.onTouchEvent(widget, buffer, event);
                }
            });
        }
    }
}

然后在你的Item布局里替换:

<com.yourpackage.ActivityLinkTextView
    android:id="@+id/tv_url"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:autoLink="web" />

方案二:在Adapter中手动设置可点击链接

这种方法不需要修改布局,直接在Adapter的getView方法里手动处理链接,灵活性更高:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_url, parent, false);
        holder = new ViewHolder();
        holder.tvUrl = convertView.findViewById(R.id.tv_url);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    // 获取当前item的URL数据
    String url = mDataList.get(position).getUrl();
    
    // 构建可点击的 SpannableString
    SpannableString spannableUrl = new SpannableString(url);
    spannableUrl.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View widget) {
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            // 用parent.getContext()获取Activity上下文启动Intent
            parent.getContext().startActivity(intent);
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            // 设置链接样式(蓝色+下划线)
            ds.setColor(Color.parseColor("#2196F3"));
            ds.setUnderlineText(true);
        }
    }, 0, url.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

    holder.tvUrl.setText(spannableUrl);
    holder.tvUrl.setMovementMethod(LinkMovementMethod.getInstance());
    
    return convertView;
}

static class ViewHolder {
    TextView tvUrl;
}

为什么不推荐加FLAG_ACTIVITY_NEW_TASK?

虽然给Intent加上intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)能暂时解决崩溃,但会把浏览器启动到新的任务栈里,用户按返回键时不会回到你的App,体验很糟糕,所以尽量不用这种方法。

内容的提问来源于stack exchange,提问作者BlueYeti81

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:22:50