从服务器下载数据并使用同步

时间:2017-05-15 11:02:00

标签: android client-server realm

我正在开发我的应用程序,其中存储引号。 有关我从服务器下载的报价的数据。 我想要用户下载10个引号(当时数据添加到本地数据库),如果他滚动这10个引号,将下载新数据(再次10)。 例如,在facebook磁带中(将数据添加到本地db)。 但我还需要将本地数据库与服务器数据库同步。 我不明白如何将这一切结合起来。

下载数据 - 在这里,我从服务器db的id传递要从中下载的id。

class DownloadAndParseJson extends AsyncTask<Integer, Void, ArrayList<QuoteObject>> {

    interface AsyncResponse {
        void processFinish(ArrayList<QuoteObject> output);
    }

    private AsyncResponse delegate = null;

    DownloadAndParseJson(AsyncResponse delegate){
        this.delegate = delegate;
    }

    private static final String TAG = "###" + "DownloadAndParseJson";

    @Override
    protected ArrayList<QuoteObject> doInBackground(Integer... params) {

        Log.i(TAG, "Starting download quotes from " + params[0] + " id");
        if (params.length == 0) {
            return null;
        }
        int id = params[0];

        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;
        String countriesJsonStr = null;

        try {
            final String BASIC_URL = "http://*******.com";
            final String ID_PARAM = "id";

            Uri builtUri = Uri.parse(BASIC_URL).buildUpon()
                    .appendQueryParameter(ID_PARAM, Integer.toString(id))
                    .build();

            URL url = new URL(builtUri.toString());
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            InputStream inputStream = urlConnection.getInputStream();
            StringBuffer buffer = new StringBuffer();
            if (inputStream == null) {
                return null;
            }
            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line + "\n");
            }

            if (buffer.length() == 0) {
                return null;
            }
            countriesJsonStr = buffer.toString();
            Log.v(TAG, "download end");
        } catch (IOException e) {
            Log.e(TAG, "Error", e);
            return null;
        } finally {

            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (final IOException e) {
                    Log.e(TAG, "Error", e);
                }
            }
        }

        Log.i(TAG, "End download quotes");
        return getArrayParsedJson(countriesJsonStr);
    }

    @Override
    protected void onPostExecute(ArrayList<QuoteObject> result) {
        Log.i(TAG, "Downloaded " + result.size() + " quotes");
        delegate.processFinish(result);
    }

    private  ArrayList<QuoteObject> getArrayParsedJson(String jsonStr){
        Gson gson = new Gson();
        Type collectionType = new TypeToken<ArrayList<QuoteObject>>(){}.getType();
        return gson.fromJson(jsonStr, collectionType);
    }
}

使用数据库 - 这里我存储引用对象

public class RealmHelper {

    private static final String TAG = "###" + "RealmHelper";
    Context context;

    public RealmHelper(Context context) {
        this.context = context;
    }

    public void write(ArrayList<QuoteObject> quoteObjectArrayList) {

        Realm.init(context);
        Realm realm = Realm.getDefaultInstance();
        realm.beginTransaction();

        for (QuoteObject quoteObject : quoteObjectArrayList){
            realm.copyToRealm(quoteObject);
        }
        realm.commitTransaction();
    }

    public ArrayList<QuoteObject> read() {

        Realm.init(context);
        Realm realm = Realm.getDefaultInstance();

        return new ArrayList<>(realm.where(QuoteObject.class).findAll());
    }

    public void delete() {
        Realm.init(context);
        Realm realm = Realm.getDefaultInstance();
        final RealmResults<QuoteObject> countries = realm.where(QuoteObject.class).findAll();

        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                countries.deleteAllFromRealm();
                Log.i(TAG, "size = " + countries.size());
            }
        });
    }
}

MainActivity

public class MainActivity extends AppCompatActivity
       implements  DownloadAndParseJson.AsyncResponse{

        .
        .
    RVAdapter adapter;
    private ArrayList<QuoteObject> quoteObjectArrayList;
        .
        .

         protected void onCreate(){
       .
       .
       .
    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
            recyclerView.setHasFixedSize(true);
            LinearLayoutManager layoutManager = new LinearLayoutManager(this);
            recyclerView.setLayoutManager(layoutManager);
            adapter = new RVAdapter(this, quoteObjectArrayList);
            recyclerView.setAdapter(adapter);
        }

        @Override
    public void processFinish(ArrayList<QuoteObject> output) {
        if (output.size() != 0) {
            quoteObjectArrayList = output;
            Log.i(TAG, "processFinish() returned outputArray size " + output.size());
        }   else
            Toast.makeText(this, "Not found quotes", Toast.LENGTH_SHORT).show();
    }

RecyclerView.Adapter - 使用卡片视图显示引号。

class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder>
     implements  DownloadAndParseJson.AsyncResponse{

    private static final String TAG = "###" + "RVAdapter";

    private Context context;
    private boolean hasMoreItems;
    private ArrayList<QuoteObject> quoteObjectArrayList;

    RVAdapter(Context context, ArrayList<QuoteObject> quoteObjectArrayList){
        this.context = context;
        this.hasMoreItems = true;
        this.quoteObjectArrayList = quoteObjectArrayList;

        Log.i(TAG, "quoteObjectArrayList = " + quoteObjectArrayList.size());

    }

    private void notifyNoMoreItems(){
        hasMoreItems = false;
        Toast.makeText(context, "No More Items", Toast.LENGTH_SHORT).show();
    }

    @Override
    public RVAdapter.PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.card_of_quote, viewGroup, false);

        return new PersonViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final RVAdapter.PersonViewHolder holder, int position) {

        Log.i(TAG, "Card position = " + position);

        if (position == quoteObjectArrayList.size() && hasMoreItems){
            new DownloadAndParseJson(this).execute(Integer.parseInt(quoteObjectArrayList.get(position).getId()));
        }
        holder.contentOfQuote.setText(quoteObjectArrayList.get(position).getQuote());
        holder.authorQuote.setText(quoteObjectArrayList.get(position).getAuthor());

        holder.ratingBar.setOnRatingChangeListener(new MaterialRatingBar.OnRatingChangeListener() {
            @Override
            public void onRatingChanged(MaterialRatingBar ratingBar, float rating) {
                //ratingBar.setRight(Integer.parseInt(quoteObjectArrayList.get(position).getId()));
            }
        });

        holder.btnShareQuote.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent sendIntent = new Intent();
                sendIntent.setAction(Intent.ACTION_SEND);
                sendIntent.putExtra(Intent.EXTRA_TEXT, holder.contentOfQuote.getText()
                                                + "\n" + holder.authorQuote.getText() );
                sendIntent.setType("text/plain");
                context.startActivity(sendIntent);
            }
        });

        holder.btnViewComment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //View Comments
            }
        });

    }

    @Override
    public int getItemCount() {
        return quoteObjectArrayList.size();
    }

    @Override
    public void processFinish(ArrayList<QuoteObject> output) {
        if (output.size() != 0) {
            quoteObjectArrayList.addAll(output);
            Log.i(TAG, "Total quoteArray Size = " + quoteObjectArrayList.size());
            new RealmHelper(context).write(output); // NEED separate throw
        } else notifyNoMoreItems();
    }

    static class PersonViewHolder extends RecyclerView.ViewHolder {

        CardView cardView;

        TextView contentOfQuote, authorQuote;

        MaterialRatingBar ratingBar;

        ImageButton btnViewComment, btnShareQuote;
        TextView rating;

        public PersonViewHolder(View itemView) {
            super(itemView);

            this.cardView = (CardView) itemView.findViewById(R.id.cardView);

            this.contentOfQuote = (TextView) itemView.findViewById(R.id.contentOfQuote);
            this.authorQuote = (TextView) itemView.findViewById(R.id.authorQuote);

            this.btnViewComment = (ImageButton) itemView.findViewById(R.id.btnViewComment);
            this.btnShareQuote = (ImageButton) itemView.findViewById(R.id.btnShareQuote);

            this.ratingBar = (MaterialRatingBar) itemView.findViewById(R.id.ratingBar);
            this.rating = (TextView) itemView.findViewById(R.id.txtRating);
        }
    }
}

现在我需要将所有这些结合起来。

结果应该是:

  1. 从本地数据库开始。
    • 如果没有数据 - 下载新的(10个引号)。
    • 否则从本地数据库中获取数据直到它们用完为止
  2. 从服务器bd下载10个引号,添加到本地并显示它们。 或者如果没有数据打印出来。
  3. 将本地bd与服务器同步。
  4. 请帮帮我。

    感谢。

1 个答案:

答案 0 :(得分:1)

如果您将RealmResults与RealmChangeListener和Realm的通知系统一起使用,那么这将更加容易。请参阅official documentation

        Button btn = new Button(this);
        btn.SetBackgroundResource(Resource.Drawable.RoundedButton);

class DownloadAndParseJson extends AsyncTask<Integer, Void, Void> {
    DownloadAndParseJson(){
    }

    private static final String TAG = "###" + "DownloadAndParseJson";

    @Override
    protected Void doInBackground(Integer... params) {
        Log.i(TAG, "Starting download quotes from " + params[0] + " id");
        if (params.length == 0) {
            return null;
        }
        int id = params[0];
        try {
            final List<QuoteObject> quotes = retrofitService.getQuotes(id).execute().body();
            if(quotes == null) {
                throw new RuntimeException("Download failed");
            }
            try(Realm realm = Realm.getDefaultInstance()) {
                realm.executeTransaction(new Realm.Transaction() {
                    @Override
                    public void execute(Realm realm) {
                        realm.insert(quotes);
                    }
                });
            }
        } catch (Exception e) {
            Log.e(TAG, "Error", e);
            return null;
        } 
        Log.i(TAG, "End download quotes");
        return null;
    }

    @Override
    protected void onPostExecute(Void ignored) {
    }
}

class RVAdapter extends RealmRecyclerViewAdapter<QuoteObject, RVAdapter.PersonViewHolder> {
    private static final String TAG = "###" + "RVAdapter";

    RVAdapter(OrderedRealmCollection<QuoteObject> quotes) {
        super(quotes, true);
    }

    // onCreateViewHolder

    // onBindViewHolder

    // view holder
}

和一些“确实下载了所有”的逻辑,虽然这需要更聪明的错误处理;并且“正在下载数据”,这样当您向下滚动时就不会发出垃圾邮件请求。