1

私はAndroidの開発にはかなり新しく、現在は複数の都市の明日の天気を表示するアプリを作成しようとしています。申し訳ありませんが、私はこの質問で使用するかもしれません。私が到達したい何Android。データベースからデータを取得し、ネットワーククエリを行います。実装方法

のAppは、DBから取得したデータに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(); 
} 

見ての通り、都市はonCreateLoader(int i, Bundle bundle)List<String> cities = new ArrayList<>();を経由して "ハードコードさ" です。だから、私は自分のアプリに都市のSQLストレージを実装することに決めました。私はContentProviderCursorAdapterを使用して、アンドロイドアプリでSQL機能を実装する方法を知っています。

問題は何ですか?

私が正しい場合は、ローカルDBにクエリを作成する場合は、LoaderManager.LoaderCallbacks<Cursor>を使用する必要があります。

残念ながら、現在のLoaderCallbacks<List<Weather>>LoaderCallbacks<Cursor>を1つのアクティビティにマージして、自分が望むように動作させる方法を想像できません。

は実は、私はCursorLoader戻ってその結果にURIを構築するために Cursor cursor = new CursorLoader(this, WeatherEntry.CONTENT_URI, projection, null, null, null);のようなものに List<String> cities = new ArrayList<>(); を変更したいです。

しかし、別のスレッドで別のスレッドとHTTPクエリ(!)でSQLクエリを作成する必要があります。私たちはネストされたスレッド/ローダ(SQLクエリの範囲内でhttpクエリを実行し、List<T>を返す)を行うべきですか?たとえそれが可能なのか想像もできません...

私を助けてください、私は立ち往生しました!

答えて

1

[OK]を私は最初の視力では明らかでしたが、私は最後に問題を解決しました。我々上記の質問で

は、ハードコードされた都市のリストを持っていた:

List<String> cities = new ArrayList<>(); 
cities.add("London,uk"); 
cities.add("Kiev,ua"); 
cities.add("Berlin,de"); 
cities.add("Dubai,ae"); 

私たちはこのように、DBクエリにそれを変更すると仮定した場合でも:

// Connect to a DB 
... 
Cursor forecastCitiesDataCursor = mDb.query(true, WeatherContract.WeatherEntry.TABLE_NAME, projection, 
        null, null, null, 
        null, null, null); 
... 
// Fetch data from cursor 

。 ..私はメインスレッドでそのSQLクエリを持っています。だから我々は解決策が必要です。

このSQLクエリをCustomLoaderクラスに入れ、コンストラクタに必要なパラメータを渡します(私の場合は、SharedPreferencesパラメータを使用してHTTPクエリを作成しています)。ここで

は私のコードです:

WeatherActivity.java

​​

WeatherLoader.java

public class WeatherLoader extends AsyncTaskLoader<List<Weather>> { 
... 
    // Pass parameters here from WeatherActivity 
    public WeatherLoader(Context context, String tmpUnit) { 
     super(context); 
     mTempUnit = tmpUnit; 
    } 

    @Override 
    protected void onStartLoading() { 
     forceLoad(); 
    } 

    /** 
    * This is on a background thread. 
    */ 
    @Override 
    public List<Weather> loadInBackground() { 

     // List for storing built URIs 
     List<String> uriList = new ArrayList<>(); 
     // List for storing forecast cities 
     List<String> cities = new ArrayList<>(); 

     // Define a projection that specifies the columns from the table we care about. 
     ... 

     Cursor forecastCitiesDataCursor = mDb.query(true, WeatherContract.WeatherEntry.TABLE_NAME, projection, 
       null, null, null, 
       null, null, null); 

     // Get list of cities from cursor 
     ... 

     //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", mTempUnit); 
      uriBuilder.appendQueryParameter("appid", /*some id*/); 

      uriList.add(uriBuilder.toString()); 
     } 

     if (uriList == null) { 
      return null; 
     } 

     // Perform the network request, parse the response, and extract a list of forecasts. 
     List<Weather> forecasts = QueryUtils.fetchForecastData(uriList); 
     return forecasts; 
    } 

だから我々が持っているもの?

私たちは、HTTPクエリを実行するために使用されるArrayAdapterを使用して、永続的なデータストレージを実装しました。 SQLクエリは別のスレッドにあり、アプリのパフォーマンスに問題はありません。

その解決策が誰かを助けてくれることを願って、素敵な一日を!

関連する問題