簡體   English   中英

單例模式“不允許訪問構造函數”

[英]Singleton Pattern “Access to Constructor not Allowed”

我對Java比較陌生,並且自學成才,因此我希望我會缺少一些基本的了解。

背景:我正在使用想加入服務的藍牙,以便可以將接收到的信息廣播到多個活動中。 這對我的MainActivity正常,但對其他任何項目都無效。 每當從設備讀取任何其他活動的藍牙特性時,它都會讀取失敗並使程序崩潰。 我發現該特性在廣播之前為非null,但在接收到該特性時為null。 我認為這是由於錯誤地創建了兩個服務實例並從一個從未處理過的實例中讀取數據。 因此,為了消除這種可能性,我想將我的服務創建為單例。 (我想讓問題保持在主題位置,這樣就不會問了,但建議值得贊賞。)

因此,我需要一個服務(BluetoothService)的單個實例,該實例用於運行和處理某些藍牙操作。 我遇到了Singleton設計模式,這看起來就像我追求的那樣。 我以各種在線來源描述的方式實現了它:

    private static BluetoothService serviceInstance;
    private BluetoothService() {} // Error occurs here

    public static BluetoothService getSharedBluetoothService() {
        if(serviceInstance == null)
            serviceInstance = new BluetoothService();
        return serviceInstance;
    }

當一個Activity試圖綁定到服務時,我在Activity中具有如下定義的活頁夾類:

public class BtBinder extends Binder {
    BluetoothService getService() {
        return getSharedBluetoothService(); // returns reference to current service
        //return BluetoothService.this; // Line used prior to introducing a Singleton pattern.
    }
}

如果我正確理解該錯誤,則私有構造函數會導致我的MainActivity錯誤-它無法實例化Service,因為其構造函數是私有的。 如果將構造方法公開,MainActivity將無法綁定到服務。 永遠不會調用onBind(),否則它將在其他地方導致Null指針異常。

我在哪里錯了? 據我所知,我已經遵循了正確的程序。 我不確定該去哪里。

編輯:活頁夾:

@Override
public IBinder onBind(Intent intent) {
    Log.d(TAG, "Currently binding");
    BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
    mBluetoothAdapter = manager.getAdapter();   
    return myBinder; // When bound, return the whole MyLocalBinder Binder.
}

主要活動:

public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
    // ...
    BluetoothService BtService;
    boolean isBound = false;

    BluetoothBroadcast btSetupReceiver = null;
    BluetoothBroadcast resultsReceiver = null;
    boolean receiversAreRegistered = false;

        private static final String TAG = "BluetoothGattActivity";
        private static final String DEVICE_NAME = "Suspensionometer 3333";

        private BluetoothAdapter mBluetoothAdapter;
        private SparseArray<BluetoothDevice> mDevices;

        private BluetoothGatt mConnectedGatt;

        private ProgressDialog mProgress;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // Bind the service
            Intent intent = new Intent(this, BluetoothService.class);
            Log.d(TAG, "Attempting to bind to service.");
            bindService(intent, btServiceConnection, Context.BIND_AUTO_CREATE);

            // Set up BroadcastReceiver
            btSetupReceiver = new BluetoothBroadcast(){

            @Override
            public void onReceive(Context context, Intent intent) 
            {               
                // ...
        };

        resultsReceiver = new BluetoothBroadcast() {
            @Override
            public void onReceive(Context context, Intent intent)
            {
                // ...
        };
    }

您不能將Service構造函數設為私有。 Android需要能夠創建許多組件來響應設備上發生的事件。 例如,Android可以根據意圖創建Service類的實例。

您可以做的是設置一個單獨的單例對象來執行工作,然后在Service中獲取該對象。 但是,請注意服務的生命周期。 如果您的服務是為了響應意圖或startService調用而啟動的,則該服務運行的時間取決於onStartCommand的返回值(START_STICKY等)。 該文檔提供了很好的概述: http : //developer.android.com/reference/android/app/Service.html

編輯:

聽起來您主要只是需要一個公共位置來存儲服務的數據,然后當其中一個活動綁定到該服務並請求該數據時,Android創建的任何服務實例都可以獲取該數據。 看來您正在使用文檔中的“ LocalService”模式,這聽起來像是對的事情。

我不知道您的藍牙數據有多復雜,但是在Android中存儲數據的最常見方法是SharedPreferences(用於更簡單的鍵/值數據)和數據庫。 如果您認為可以擺脫SharedPreferences,則可以使用JSON將相當多的復雜性存儲為長字符串。

如果您的數據太復雜或基於表,那么Android會附帶SQLiteDatabase和相關類,以及ContentProvider類,該類提供對數據庫的URI類型訪問。

我在這里朝正確的方向前進嗎? 我現在就停下來,但是如果您需要更多說明,或者我已經脫離常規,請告訴我。

將有問題的私有更改為受保護,就可以解決問題。

在這個很棒的博客上閱讀Singletons: http//www.javaworld.com/article/2073352/core-java/simply-singleton.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM