Search code examples
androidandroid-lifecycleandroid-cursoradapterandroid-cursorloader

How to prevent a service from being called every time an activity is created?


In my activity, in its onCreate method, I call a service in order to open an internet connection to make a server request. I then save the server's data to a database, and display it in the form of a list to the UI through a CursorLoader (and CursorAdapter) in a fragment. The problem is that every time the user navigates to that activity the connection is launched again, prompting the Loader to reload the data, thus displaying the same list more than once. So while the list should read the same every time, e.g.:

  • Sports
  • Weather
  • News

what is actually happening is that each time the user navigates back to the host activity the list is being displayed again, so if a user navigated to the activity 3 times the list would be displayed like so:

  • Sports
  • Weather
  • News
  • Sports
  • Weather
  • News
  • Sports
  • Weather
  • News

How can I prevent the activity from calling the service every time? Also, could the problem be the Loader?

Code for the activity and fragment:

Activity:

public class HappinessActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_happiness);
    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.happiness_container, new HappinessFragment())
                .commit();
    }
        Intent intent = new Intent(this, ArticleService.class);
        intent.putExtra(ArticleService.CATEGORY_EXTRA, 1);
        startService(intent);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_happiness, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

and Fragment:

public class HappinessFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {

private String LOG_TAG = this.getClass().getSimpleName();

private static final int ARTICLE_LOADER = 0;
private ArticleAdapter mAdapter;
private ListView mListView;

public HappinessFragment() {
}

private static final String[] ARTICLE_COLUMNS = {
        ArticleContract.ArticlesEntry._ID,
        ArticleContract.ArticlesEntry.COLUMN_CATEGORY_ID,
        ArticleContract.ArticlesEntry.COLUMN_ARTICLE_ID,
        ArticleContract.ArticlesEntry.COLUMN_AUTHOR,
        ArticleContract.ArticlesEntry.COLUMN_TITLE,
        ArticleContract.ArticlesEntry.COLUMN_URL
};

static final int COL_ART_ID = 0;
static final int COL_CATEGORY_ID = 1;
static final int COL_ARTICLE_ID = 2;
static final int COL_AUTHOR = 3;
static final int COL_TITLE = 4;
static final int COL_URL = 5;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    mAdapter = new ArticleAdapter(getActivity(), null, 0);
    View rootView = inflater.inflate(R.layout.fragment_happiness, container, false);

    mListView = (ListView) rootView.findViewById(R.id.happiness_list);
    mListView.setAdapter(mAdapter);

    return rootView;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    getActivity().getLoaderManager().initLoader(ARTICLE_LOADER, null, this);
}

@Override
public void onPause() {
    super.onPause();
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    //Uri queryUri = ArticleContract.ArticlesEntry.buildArticleList();
    String URL = "content://app.quantumfinality.com.soulremedy/articles";
    Uri uri = Uri.parse(URL);
    Log.v("CursorLoader", "Table path built");
    String sortOrder = ArticleContract.ArticlesEntry._ID;

    return new CursorLoader(getActivity(),
            uri,
            ARTICLE_COLUMNS,
            null,
            null,
            sortOrder);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    mAdapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    mAdapter.swapCursor(null);

}
}

Thank you in advance. Any help is greatly appreciated as there's a looming deadline for the project.


Solution

  • you can try two approaches

    1 create a boolean and check if its first time is being called and call your code

    //static variable
    static boolean firstTyme = true;     
    // in onDestroy of your service class set it to false. 
    // so with that the service takes care of the toggling
    /// now you check the boolean in your activity onCreate if its true/false
    

    2 the second way is to check if the service is already running, if not call it, if it is do not call it

    boolean running =false;
    ActivityManager manager = (ActivityManager) getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (YourServiceClass.getName().equals(service.service.getClassName())) {
                // it checks out to be running so you let fly
                running = true;
                break;
            }
        }
     if(!running){ // if running is false
        // call your intent funtions
      }