首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 自訂 Toast 顯示異常?LayoutInflater 需從 Context 取得、類別勿繼承 Activity

     編輯:程式設計綜合問答

錯誤代碼分析

public class SMSToast extends Activity { // ❌ 錯誤:Toast 工具類不應繼承 Activity
    public void showToast(Context context, String message) {
        LayoutInflater inflater = getLayoutInflater(); // ❌ 錯誤:Activity 尚未附加到視窗,getLayoutInflater() 可能失效
        View layout = inflater.inflate(R.layout.toast_sms, (ViewGroup) findViewById(R.id.toast_sms_root));
        ...
    }
}

// BroadcastReceiver 中
SMSToast toast = new SMSToast(); // 實例化 Activity 但未經系統啟動,極度危險
toast.showToast(context, "...");

核心問題

  1. 類別繼承 Activity:Activity 必須由系統透過 Intent 啟動,手動 new Activity() 會導致生命週期缺失、Context 不完整、資源洩漏。
  2. LayoutInflater 來源錯誤:應從 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) 取得,而非 Activity.getLayoutInflater()。
  3. Toast 建立方式:直接 new Toast(context) 並 setView() 即可,無需繼承任何類別。

正確實作:獨立工具類

public final class CustomToast {
    private CustomToast() {} // 防止實例化

    public static void show(Context context, String message, int duration) {
        // 1. 從 Context 取得 LayoutInflater
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        // 2. 充氣自訂佈局(root 參數傳 null,因 Toast 會自行加入 WindowManager)
        View layout = inflater.inflate(R.layout.toast_sms, null);
        // 3. 填充內容
        TextView text = layout.findViewById(R.id.toast_sms_text);
        text.setText(message);
        // 4. 建立並顯示 Toast
        Toast toast = new Toast(context);
        toast.setDuration(duration);
        toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
        toast.setView(layout);
        toast.show();
    }

    // 便利多載
    public static void showShort(Context context, String message) {
        show(context, message, Toast.LENGTH_SHORT);
    }
    public static void showLong(Context context, String message) {
        show(context, message, Toast.LENGTH_LONG);
    }
}

BroadcastReceiver 中呼叫


@Override
public void onReceive(Context context, Intent intent) {
    String msg = "Received SMS from: " + msg_from + " Content: " + msgBody;
    CustomToast.showLong(context, msg); // 直接靜態呼叫,傳入 onReceive 的 context
}

自訂佈局範例 (res/layout/toast_sms.xml)

<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:id="@+id/toast_sms_root"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/toast_bg_rounded"
    android:padding="12dp"
    android:orientation="horizontal">

    <ImageView
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:src="@drawable/ic_sms"
        android:contentDescription="@string/sms_icon" />

    <TextView
        android:id="@+id/toast_sms_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:textColor="@android:color/white"
        android:textSize="14sp"
        android:maxWidth="280dp"
        android:ellipsize="end"
        android:singleLine="false" />
</LinearLayout>

關鍵原則總結

  1. Toast 工具類**不繼承 Activity/ContextWrapper**,僅提供靜態方法。
  2. LayoutInflater **必須從傳入的 Context 取得系統服務**。
  3. inflater.inflate(layoutRes, null):Toast 會自行將 View 加入 WindowManager,root 應為 null。
  4. 在 BroadcastReceiver.onReceive 中直接使用參數 context,該 Context 已具備顯示 Toast 的能力。

遵循此模式,自訂 Toast 即可在任何元件(Activity、Service、Receiver、Application)中穩定顯示。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved