Я довольно новичок в разработке Android и в настоящее время пытаюсь написать приложение, которое покажет завтрашнюю погоду в нескольких городах. Извините за любые неиспользуемые терминалы, которые я мог бы использовать в этом вопросе.Android. Извлеките данные из базы данных и затем выполните сетевой запрос. Как реализовать?
То, что я хочу, чтобы достичь:
App будет получать данные из локальной базы данных, а затем построить HTTP запрос на данные, извлекаемых из БД, получить ответ JSON и сформировать список элементов.
То, что я в настоящее время:
Все, кроме функциональности SQL.
Это снимок моего основного кода активности. Я использую LoaderCallbacks<List<Weather>>
для создания URI с необходимыми параметрами в onCreateLoader(int i, Bundle bundle)
, отправьте HTTP-запрос и получите данные через WeatherLoader(this, uriList)
, а результаты элементов формы - List
, используя 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();
}
Как вы видите, города являются "жёстко" через List<String> cities = new ArrayList<>();
в onCreateLoader(int i, Bundle bundle)
. Вот почему я решил реализовать SQL-хранилище городов в своем приложении. Я знаю, как реализовать функциональность SQL в приложении Android, используя ContentProvider
и CursorAdapter
.
Так в чем проблема?
Если я прав, мы должны использовать LoaderManager.LoaderCallbacks<Cursor>
, если мы хотим сделать запрос к локальной базе данных.
К сожалению, я не могу представить, как объединить текущие LoaderCallbacks<List<Weather>>
и LoaderCallbacks<Cursor>
в одном действии, чтобы заставить его работать так, как я хочу.
На самом деле, я хочу изменить List<String> cities = new ArrayList<>();
на что-то вроде Cursor cursor = new CursorLoader(this, WeatherEntry.CONTENT_URI, projection, null, null, null);
построить URI на результаты, которые CursorLoader
возвращается.
Но мы должны сделать SQL-запрос в отдельном потоке и HTTP-запросе также (!) В отдельном потоке. Должны ли мы делать вложенные потоки/загрузчики (HTTP-запрос в области sql-выборки данных и возвращать List<T>
)? Даже не представляю, как это можно сделать, если так ...
Помогите мне, пожалуйста, я застрял!