我想只发一次凌空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();
}
}
}
答案 0 :(得分:2)
我想只发一次凌空http请求,它应该是在安装应用程序的时候。
安装应用时,您无法获得控制权。
我是否需要在onCreate()方法中做一些特别的事情来确保应用程序仅在截击请求完成后运行?
Volley是异步的。这是使用Volley背后的完整和完整的观点。在您致电requestQueue.add(request);
之后,您的onCreate()
方法会立即继续执行,而Volley会在后台线程上执行网络I / O.
有些选择是:
摆脱所有Volley代码,将首发数据打包为APK作为资产,using SQLiteAssetHelper
在首次运行应用时部署打包数据库。
不要使用Volley。相反,使用具有同步网络I / O选项(HttpURLConnection
,OkHttp等)的内容,并在此处执行同步网络I / O.您应该始终在后台线程上使用SQLiteOpenHelper
子类,以防需要创建或更新数据库。因此,应始终在后台线程上调用onCreate()
的{{1}}方法,并且不需要网络I / O的另一个后台线程。然后,您可以确保在SQLiteOpenHelper
结束时您的起始数据存在...除非您没有Internet连接,或者您的服务器已关闭等等。
将所有初始化逻辑移至其他位置,例如onCreate()
。让它创建数据库(使用IntentService
自己的后台线程)并让它进行网络I / O(同样,使用同步API,因为IntentService
有自己的后台线程)。只有IntentService
完成其工作后才能启动您的用户界面。您可以通过某种重试策略更好地处理连接错误,同时在该工作进行时向用户提供一些临时UI(例如IntentService
)。