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.
What I want to reach:
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.
What I currently have:
Everything except SQL functionality.
Here is the snapshot of my main activity code. I use LoaderCallbacks<List<Weather>>
to build URI with needed parameters in onCreateLoader(int i, Bundle bundle)
, send HTTP query and get the data via WeatherLoader(this, uriList)
, and form elements results in a List
using WeatherAdapter
.
public class WeatherActivity extends AppCompatActivity
implements LoaderCallbacks<List<Weather>>,
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<Weather>());
weatherListView.setAdapter(mAdapter);
...
weatherListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> 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 && 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<List<Weather>> 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<String> uriList = new ArrayList<>();
/***
*
* Here we input cities for which we want to see the forecast
*
* ***/
List<String> cities = new ArrayList<>();
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<List<Weather>> loader, List<Weather> 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 && !weatherList.isEmpty()) {
mAdapter.addAll(weatherList);
}
}
@Override
public void onLoaderReset(Loader<List<Weather>> loader) {
mAdapter.clear();
}
As you see, cities are "hardcoded" via List<String> cities = new ArrayList<>();
in onCreateLoader(int i, Bundle bundle)
. 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 ContentProvider
and CursorAdapter
.
So what's the problem?
If I am correct we should use LoaderManager.LoaderCallbacks<Cursor>
if we want to make a query to a local DB.
Unfortunately, I can't imagine how to merge current LoaderCallbacks<List<Weather>>
and LoaderCallbacks<Cursor>
in one activity to make it work as I want.
Actually, I want to change
List<String> cities = new ArrayList<>();
on something like
Cursor cursor = new CursorLoader(this, WeatherEntry.CONTENT_URI, projection, null, null, null);
to build the URI on the results that CursorLoader
returns.
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 List<T>
)? Even can't imagine how it's possible to do, if so...
Help me please, I've stuck!