title: Android. Fetch data from database and then make network query. How to implement?
body: <p>I'm pretty new to an Android development and currently trying to write an app that will show tomorrow's weather of multiple cities. Sorry for any incorrent termins that I might use in this question.</p>
  
  <p><strong><em>What I want to reach:</em></strong></p>
  
  <p>App will fetch data from local database, then build a HTTP query on the data fetched from a DB, get JSON response and form a list elements.</p>
  
  <p><strong><em>What I currently have:</em></strong></p>
  
  <p>Everything except SQL functionality.</p>
  
  <p>Here is the snapshot of my main activity code. I use <code>LoaderCallbacks&lt;List&lt;Weather&gt;&gt;</code> to build URI with needed parameters in <code>onCreateLoader(int i, Bundle bundle)</code>, send HTTP query and get the data via <code>WeatherLoader(this, uriList)</code>, and form elements results in a <code>List</code> using <code>WeatherAdapter</code>.</p>
  
  <pre><code>public class WeatherActivity extends AppCompatActivity
  implements LoaderCallbacks&lt;List&lt;Weather&gt;&gt;,
  SharedPreferences.OnSharedPreferenceChangeListener {
  
  private static final int WEATHER_LOADER_ID = 1;
  private WeatherAdapter mAdapter;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.weather_activity);
  
      ListView weatherListView = (ListView) findViewById(R.id.list);
  
      mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
      weatherListView.setEmptyView(mEmptyStateTextView);
      mAdapter = new WeatherAdapter(this, new ArrayList&lt;Weather&gt;());
      weatherListView.setAdapter(mAdapter);
  
      ...
  
      weatherListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
          @Override
          public void onItemClick(AdapterView&lt;?&gt; adapterView, View view, int position, long l) {
              Weather currentWeather = mAdapter.getItem(position);
              Uri forecastUri = Uri.parse(currentWeather.getUrl());
              Intent websiteIntent = new Intent(Intent.ACTION_VIEW, forecastUri);
              startActivity(websiteIntent);
          }
      });
  
      ConnectivityManager connMgr = (ConnectivityManager)
              getSystemService(Context.CONNECTIVITY_SERVICE);
      NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
      if (networkInfo != null &amp;&amp; networkInfo.isConnected()) {
          LoaderManager loaderManager = getLoaderManager();
          loaderManager.initLoader(WEATHER_LOADER_ID, null, this);
      } else {
          View loadingIndicator = findViewById(R.id.loading_indicator);
          loadingIndicator.setVisibility(View.GONE);
          mEmptyStateTextView.setText(R.string.no_internet_connection);
      }
  }
  
  @Override
  public Loader&lt;List&lt;Weather&gt;&gt; onCreateLoader(int i, Bundle bundle) {
  
      SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
      String tempUnit = sharedPrefs.getString(
              getString(R.string.settings_temp_unit_key),
              getString(R.string.settings_temp_unit_default));
  
      List&lt;String&gt; uriList = new ArrayList&lt;&gt;();
  
      /*** 
       *
       * Here we input cities for which we want to see the forecast
       *
       * ***/
  
      List&lt;String&gt; cities = new ArrayList&lt;&gt;();
      cities.add("London,uk");
      cities.add("Kiev,ua");
      cities.add("Berlin,de");
      cities.add("Dubai,ae");
  
      //For each city in the list generate URI and put it in the URIs list
      for (String city : cities){
          Uri baseUri = Uri.parse(OWM_REQUEST_URL);
          Uri.Builder uriBuilder = baseUri.buildUpon();
  
          uriBuilder.appendQueryParameter("q", city);
          uriBuilder.appendQueryParameter("cnt", "16");
          uriBuilder.appendQueryParameter("units", tempUnit);
          uriBuilder.appendQueryParameter("appid", "some_key");
  
          uriList.add(uriBuilder.toString());
      }
  
      return new WeatherLoader(this, uriList);
  }
  
  @Override
  public void onLoadFinished(Loader&lt;List&lt;Weather&gt;&gt; loader, List&lt;Weather&gt; weatherList) {
  
      mAdapter.clear();
  
      // If there is a valid list of forecasts, then add them to the adapter's
      // data set. This will trigger the ListView to update.
      if (weatherList != null &amp;&amp; !weatherList.isEmpty()) {
          mAdapter.addAll(weatherList);
      }
  }
  
  @Override
  public void onLoaderReset(Loader&lt;List&lt;Weather&gt;&gt; loader) {
      mAdapter.clear();
  }
  </code></pre>
  
  <p>As you see, cities are "hardcoded" via <code>List&lt;String&gt; cities = new ArrayList&lt;&gt;();</code> in <code>onCreateLoader(int i, Bundle bundle)</code>. That's why I've decided to implement SQL storage of cities in my app. I know how to implement SQL functionality in android app using <code>ContentProvider</code> and <code>CursorAdapter</code>.</p>
  
  <p><strong><em>So what's the problem?</em></strong></p>
  
  <p>If I am correct we should use <code>LoaderManager.LoaderCallbacks&lt;Cursor&gt;</code> if we want to make a query to a local DB. </p>
  
  <p>Unfortunately, I can't imagine how to merge current <code>LoaderCallbacks&lt;List&lt;Weather&gt;&gt;</code> and <code>LoaderCallbacks&lt;Cursor&gt;</code> in one activity to make it work as I want.</p>
  
  <p>Actually, I want to change
  <code>List&lt;String&gt; cities = new ArrayList&lt;&gt;();</code>
  on something like
  <code>Cursor cursor = new CursorLoader(this, WeatherEntry.CONTENT_URI, projection, null, null, null);</code> to build the URI on the results that <code>CursorLoader</code> returns.</p>
  
  <p>But, we should make SQL query in separate thread and HTTP query also(!) in separate thread. Should we do nested threads/loaders (http query in a scope of sql fetching data and return a <code>List&lt;T&gt;</code>)? Even can't imagine how it's possible to do, if so...</p>
  
  <p>Help me please, I've stuck!</p>