Android service Create a new instance of the Singleton Class

I use the Singleton class to store some data outside the application. This is some queue.

I am creating a Singleton Class Instance method of onCreatemy class Application.

 @Override
 public void onCreate() {
    super.onCreate();
    mInstance = this;
    mContext = getApplicationContext();
    Queue.getInstance(); // this is my singleton class instance
  }

After that I add data inside this singleton class in my actions

Queue.getInstance().addItem(qItem);
Log.d(Constants.TAG, "Added Item Queue Size: "+Queue.getInstance().getQueueList().size());

So far, this is all working fine. I can access the data in mine Activitiesand ListView Adapterhowever, when I start the service and try to access the data of the onCreateservice

Log.d(Constants.TAG, "Playing Item Queue Size: "+Queue.getInstance().getQueueList().size()+" Current Item No. "+Queue.getInstance().getCurrentPlayingItem());
String url = Queue.getInstance().getQueueItem(Queue.getInstance().getCurrentPlayingItem()).getLinkUrl();

My Singleton Instance becomes null, and my singleton creates a new instance. This results in data loss within the service.

The following is the stream of my error.

  • When starting the Create Instance - Working application
  • Add data from operations and adapters - Work
  • - , Singleton

Singleton Class

import java.util.ArrayList;

import com.taazi.utils.Constants;

import android.util.Log;

public class Queue {
    private ArrayList<QueueItem> mQueueList;
    static Queue mInstance;
    private int currentPlayingItem=0;

    private Queue(){
        mQueueList = new ArrayList<QueueItem>();
    }

    public static Queue getInstance(){
        if(mInstance == null){
            mInstance = new Queue();
            Log.d(Constants.TAG, "New Instance");
        }
        return mInstance;
    }

    public void addItem(QueueItem item){
        mQueueList.add(item);
    }

    public void removeItem(int position){
        mQueueList.remove(position);
    }

    public ArrayList<QueueItem> getQueueList(){
        return mQueueList;
    }

    public QueueItem getQueueItem(int position){
        return mQueueList.get(position);
    }

    public int getCurrentPlayingItem() {
        return currentPlayingItem;
    }

    public void setCurrentPlayingItem(int currentPlayingItem) {
        this.currentPlayingItem = currentPlayingItem;
    }


}

AudioPlayBackService.Java

package com.taazi.services;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.IBinder;
import android.util.Log;

import com.taazi.helper.NotificationHelperNew;
import com.taazi.models.Queue;
import com.taazi.models.QueueItem;
import com.taazi.utils.Constants;

public class AudioPlayBackService extends Service {

    /**
     * Called to go toggle between pausing and playing the music
     */
    public static final String TOGGLEPAUSE_ACTION = "com.taazi.services.togglepause";

    /**
     * Called to go to pause the playback
     */
    public static final String PAUSE_ACTION = "com.taazi.services.pause";

    /**
     * Called to go to stop the playback
     */
    public static final String STOP_ACTION = "com.taazi.services.stop";

    /**
     * Called to go to the previous track
     */
    public static final String PREVIOUS_ACTION = "com.taazi.services.previous";

    /**
     * Called to go to the next track
     */
    public static final String NEXT_ACTION = "com.taazi.services.next";

    /**
     * Used to build the notification
     */
    private NotificationHelperNew mNotificationHelper;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    MediaPlayer player;

    @Override
    public void onCreate() {
        super.onCreate();
     // Initialize the notification helper
        mNotificationHelper = new NotificationHelperNew(this);

        Log.d(Constants.TAG, "Playing Item Queue Size: "+Queue.getInstance().getQueueList().size()+" Current Item No. "+Queue.getInstance().getCurrentPlayingItem());
        String url = Queue.getInstance().getQueueItem(Queue.getInstance().getCurrentPlayingItem()).getLinkUrl();
        player = MediaPlayer.create(this, Uri.parse(url));
        player.setLooping(false); // Set looping
        updateNotification();
    }
    public int onStartCommand(Intent intent, int flags, int startId) {
        player.start();
        return 1;
    }

    public void onStart(Intent intent, int startId) {
        // TO DO
    }
    public IBinder onUnBind(Intent arg0) {
        // TO DO Auto-generated method
        return null;
    }

    public void onStop() {

    }
    public void onPause() {

    }
    @Override
    public void onDestroy() {
        mNotificationHelper.killNotification();
        player.stop();
        player.release();
    }

    @Override
    public void onLowMemory() {

    }

    /**
     * Updates the notification, considering the current play and activity state
     */
    private void updateNotification() {
        QueueItem item =  Queue.getInstance().getQueueItem(Queue.getInstance().getCurrentPlayingItem());
            mNotificationHelper.buildNotification("", item.getArtist(),
                    item.getTitle(), (long)50, null, true);
    }

}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.taazi.android"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="20" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.GET_TASKS" />


    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <application
        android:name="com.taazi.app.AppController"
        android:allowBackup="true"
        android:hardwareAccelerated="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.Apptheme" >
        <activity
            android:name="com.taazi.activities.MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Music service -->
        <service
            android:name="com.taazi.services.AudioPlayBackService"
            android:label="@string/app_name"
            android:process=":main" />

    </application>

</manifest>
+4
2

Service , Application, null.

>

Service :

android:process=":main"

, HandlerThread .

+5

, , .

    // package, imports ...

    public class Queue {

        // Make 100% sure your QueueItem class is immutable! Otherwise it will not be thread safe!
        // Also, it makes more sense (more readable) to put your QueueItem together with your Queue class 
        public static class QueueItem {
            //...
        }

        // changed the below line - was: private ArrayList<String> mQueueList; 
        // (search for programming against an interface rather than an implementation)
        private List<QueueItem> mQueueList; 
        static Queue mInstance;
        private int currentPlayingItem=0;

        private Queue() {
            // See javadoc on the synchronizedList() method. 
            mQueueList = Collections.synchronizedList(new ArrayList<QueueItem>());
        }

        // Added synchronized keyword below 
        public synchronized static Queue getInstance(){
            if(mInstance == null){
                mInstance = new Queue();
                Log.d(Constants.TAG, "New Instance");
            }
            return mInstance;
        }

        // Thread safe as it is (provided that QueueItem is immutable)
        public void addItem(QueueItem item){
            mQueueList.add(item);
        }

        // Thread safe as it is
        public void removeItem(int position){
            mQueueList.remove(position);
        }

        // This method is actually inherently flawed, remove this method - you should never need 
        // mQueueList - if you do need this method then your code is structured wrong.
        // changed the below line - was: public ArrayList<QueueItem> getQueueList(){
        /*public List<QueueItem> getQueueList(){
            return mQueueList;
        }*/

        // Thread safe as it is (provided that QueueItem is immutable) 
        public QueueItem getQueueItem(int position){
            return mQueueList.get(position);
        }

        // Made this method synchronized (and thus thread safe) - very unlikely to cause performance issue.
        public synchronized int getCurrentPlayingItem() {
            return currentPlayingItem;
        }

        // Made this method synchronized (and thus thread safe) - very unlikely to cause performance issue.
        public synchronized void setCurrentPlayingItem(int currentPlayingItem) {
            this.currentPlayingItem = currentPlayingItem;
        }


    }
+1

Source: https://habr.com/ru/post/1547540/


All Articles