在应用安装期间发出volley http请求

时间:2017-02-24 15:19:07

标签: android android-fragments android-sqlite android-volley

我想只发一次凌空http请求,它应该是在安装应用程序的时候。

我通过在SQLiteOpenHelper类的onCreate()方法中生成http请求来实现此目的,该类从远程MySQL中获取数据以备使用。然而,我遇到的问题是,在应用程序安装完成后,应用程序将显示空白屏幕(主要活动上托管的片段)。但是,当我关闭应用程序并第二次打开时,它可以将SQLite中的数据提取到屏幕上。

我是否需要在onCreate()方法中做些特别的事情确保应用仅在截击请求完成后运行?

这是我的代码。 SQLiteOpenHelper onCreate()

   @Override
    public void onCreate(final SQLiteDatabase db) {
        db.execSQL(CREATE_NOTICE_TABLE);
        db.execSQL(CREATE_ROSTER_TABLE);

        /*Perform One time sync operations from remote MySQL*/
        requestQueue = Volley.newRequestQueue(ContextGetter.getAppContext());

        JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, URL, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                if(response == null || response.length() == 0){
                    return;
                }

                if(response.has("notices")){
                    //Save to notices table
                    try {
                        JSONArray notices = response.getJSONArray("notices");
                        for (int i = 0; i < notices.length(); i++) {
                           JSONObject noticeObject = notices.getJSONObject(i);
                            String noticeID = noticeObject.getString(NOTICE_ID_KEY);
                            String noticeTitle = noticeObject.getString(NOTICE_TITLE_KEY);
                            String noticeBody = noticeObject.getString(NOTICE_BODY_KEY);
                            String dateCreated = noticeObject.getString(NOTICE_DATE_KEY);

                            NoticeItem noticeItem = new NoticeItem();
                            noticeItem.setId(Integer.parseInt(noticeID));
                            noticeItem.setTitle(noticeTitle);
                            noticeItem.setBody(noticeBody);
                            try {
                                noticeItem.setDate(formatDate(dateCreated));
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }

                            //Save to SQLite
                            createNoticeBoard(noticeItem, db);
                        }
                    } catch (JSONException e) {
                        Log.d(TAG, "JSONException: " + e.getMessage());
                    }
                }

                //If roster available
                if(response.has("rosters")){
                    //Save to roster table
                    try {
                        JSONArray rosters = response.getJSONArray("rosters");
                        for (int i = 0; i <rosters.length() ; i++) {
                            JSONObject rosterObject = rosters.getJSONObject(i);
                            String rosterID = rosterObject.getString(ROSTER_ID_KEY);
                            String rosterOwner = rosterObject.getString(ROSTER_OWNER_KEY);
                            String rosterDate = rosterObject.getString(ROSTER_DATE_KEY);
                            String rosterShift = rosterObject.getString(ROSTER_SHIFT_KEY);

                            //Check to verify that the user actually owns that roster later by using shared preference
                            RosterItem rosterItem = new RosterItem();
                            rosterItem.setSyncNumber(Integer.parseInt(rosterID));
                            rosterItem.setStaffNumber(rosterOwner);
                            rosterItem.setShift(rosterShift);
                            try {
                                rosterItem.setDate(formatDate(rosterDate));
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                            createRoster(rosterItem, db);
                        }
                    }catch(JSONException e){
                        Log.d(TAG, "JSONException: "+ e.getMessage());
                    }
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

                Log.d(TAG, "VolleyError "+error.getMessage());
            }
        });


        //Add to requestQueue
        requestQueue.add(request);
    }

片段类

public class NoticeListFragment extends Fragment{

    private static final String TAG = "NoticeListFragment";

    private RecyclerView recyclerView;
    private NoticeListAdapter mNoticeListAdapter;


    public NoticeListFragment() {
        //Requires empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "Notices onCreate() called");

    }


    @Override
    public void onResume() {
        super.onResume();
        updateUI(); //In case data changes
        Log.d(TAG, "onResume() called");
    }


    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {


        //Inflate layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_notice_list, container, false);

        recyclerView = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view);
        recyclerView.setHasFixedSize(true);

        LinearLayoutManager linearManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(linearManager);

        updateUI();
        return rootView;
    }


    /*View Holder*/
    private class NoticeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        private NoticeItem mNoticeItem;

        public CardView mCardView;
        public TextView mTextViewTitle;
        public TextView mTextViewDate;
        public TextView mTextViewBody;

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

            mCardView = (CardView) itemView.findViewById(R.id.card_view);
            mTextViewBody = (TextView) itemView.findViewById(R.id.tv_notice_summary);
            mTextViewTitle = (TextView) itemView.findViewById(R.id.tv_notice_title);
            mTextViewDate = (TextView) itemView.findViewById(R.id.tv_notice_date);

            itemView.setOnClickListener(this);

        }

        //Bind properties to views

        private void bindNotice(NoticeItem noticeItem){
            mNoticeItem = noticeItem;
            mTextViewTitle.setText(noticeItem.getTitle());
            mTextViewDate.setText(noticeItem.getDate());
            mTextViewBody.setText(noticeItem.getSummary());

        }

        @Override
        public void onClick(View view) {

            Intent intent = NoticePagerActivity.newIntent(getActivity(), mNoticeItem.getId());
            startActivity(intent);
        }
    }

    /*Adapter*/
    private class NoticeListAdapter extends RecyclerView.Adapter<NoticeViewHolder>{

        //private Context mContext;
        private List<NoticeItem> listItems;


        //Provide a suitable constructor (depends on the kind of dataset you have)
        public NoticeListAdapter(List<NoticeItem> data) {
            //this.mContext = context;
            this.listItems = data;
        }


        @Override
        public NoticeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            //Create a new view
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.notice_lists_card, parent, false);
            //Set the view size, margin, padding and layout parameters
            NoticeViewHolder vh = new NoticeViewHolder(view);

            return vh;
        }

        @Override
        public void onBindViewHolder(NoticeViewHolder holder, int position){

            final NoticeItem noticeItem = listItems.get(position);
            //Bind data properties to views here...
            holder.bindNotice(noticeItem);

        }

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

        public void setNotices(List<NoticeItem> notices){
                listItems = notices;
        }
    }

    //Bind adapter to recycler view
    private void updateUI(){
        NoticeLab noticeLab = NoticeLab.get(getActivity());
        List<NoticeItem> notices = noticeLab.getNotices();

        if(mNoticeListAdapter == null){
            mNoticeListAdapter = new NoticeListAdapter(notices);
            recyclerView.setAdapter(mNoticeListAdapter);
        }else{

            mNoticeListAdapter.setNotices(notices);
            mNoticeListAdapter.notifyDataSetChanged();
        }

    }
}

1 个答案:

答案 0 :(得分:2)

  

我想只发一次凌空http请求,它应该是在安装应用程序的时候。

安装应用时,您无法获得控制权。

  

我是否需要在onCreate()方法中做一些特别的事情来确保应用程序仅在截击请求完成后运行?

Volley是异步的。这是使用Volley背后的完整和完整的观点。在您致电requestQueue.add(request);之后,您的onCreate()方法会立即继续执行,而Volley会在后台线程上执行网络I / O.

有些选择是:

  1. 摆脱所有Volley代码,将首发数据打包为APK作为资产,using SQLiteAssetHelper在首次运行应用时部署打包数据库。

  2. 不要使用Volley。相反,使用具有同步网络I / O选项(HttpURLConnection,OkHttp等)的内容,并在此处执行同步网络I / O.您应该始终在后台线程上使用SQLiteOpenHelper子类,以防需要创建或更新数据库。因此,应始终在后台线程上调用onCreate()的{​​{1}}方法,并且不需要网络I / O的另一个后台线程。然后,您可以确保在SQLiteOpenHelper结束时您的起始数据存在...除非您没有Internet连接,或者您的服务器已关闭等等。

  3. 将所有初始化逻辑移至其他位置,例如onCreate()。让它创建数据库(使用IntentService自己的后台线程)并让它进行网络I / O(同样,使用同步API,因为IntentService有自己的后台线程)。只有IntentService完成其工作后才能启动您的用户界面。您可以通过某种重试策略更好地处理连接错误,同时在该工作进行时向用户提供一些临时UI(例如IntentService)。