在列表视图中添加倒数计时器会在每个新行中重新启动
Posted
技术标签:
【中文标题】在列表视图中添加倒数计时器会在每个新行中重新启动【英文标题】:Adding countdown timer in listview restarts in each new row 【发布时间】:2016-02-20 04:36:45 【问题描述】:我正在从服务器获取 XML 格式的数据并将其传递给 Listview
。在添加的每一行中,都有来自xml
的参数,我想将这些参数传入CountDownTimer
,因此每一行都有其唯一的倒计时计时器。当我通过第一行时,计数器工作正常,但是当添加另一行时,第一行的计时器从头开始。此外,当我移动列表时,不可见行的计时器会从头开始。我应该如何传递它,以便它对每个都是唯一的,并且在 Listview
发生更改时不会更改?
这是我的适配器:
public class PickCallAdapter extends ArrayAdapter<CallXML>
public PickCallAdapter(Activity context)
super(context, R.layout.pick_call_cell, new ArrayList<CallXML>());
public void setBidProcessMessageThread(final Long tripId)
runOnUiThread(new Runnable()
public void run()
setBidProcessMessage(tripId);
);
public void setBidProcessMessage(Long tripId)
View view = getViewOfList(tripId);
if (view != null)
setTripProgress(tripId, view);
/**
* Trips are order by ascending tripid Therefore will use binary search
*
* @param tripId
* @return
*/
private View getViewOfList(Long tripId)
CallXML[] callXMLs = getItems();
Integer position = binarySearch(callXMLs, tripId, 0,
pickCallAdapter.getCount() - 1);
if (position != null)
int firstPosition = pickCallsView.getFirstVisiblePosition()
- pickCallsView.getHeaderViewsCount();
int cellPosition = firstPosition + position;
View wanted = pickCallsView.getChildAt(cellPosition);
return wanted;
return null;
public CallXML[] getItems()
int size = pickCallAdapter.getCount();
CallXML[] callXMLs = new CallXML[size];
for (int i = 0; i < size; i++)
callXMLs[i] = pickCallAdapter.getItem(i);
return callXMLs;
/**
* Using binary search since our list is sorted
*
* @param tripId
* @param min
* @param max
* @return
*/
private Integer binarySearch(CallXML[] callXMLs, Long tripId, int min,
int max)
if (max < min)
return null;
else
int mid = (min + max) / 2;
if (callXMLs[mid].getId().compareTo(tripId.intValue()) > 0)
return binarySearch(callXMLs, tripId, min, mid - 1);
else if (callXMLs[mid].getId().compareTo(tripId.intValue()) < 0)
return binarySearch(callXMLs, tripId, mid + 1, max);
else
return mid;
@SuppressLint("WrongViewCast")
@Override
public View getView(int position, View convertView, ViewGroup parent)
final CallXML callXML = pickCallAdapter.getItem(position);
if (callXML == null)
return null;
PickCallViewBuilder pickCallViewBuilder = new PickCallViewBuilder(
callXML, TaxiMapGoogle.this);
TextView timerText = (TextView) pickCallView.findViewById(R.id.timer);
//pickCallViewBuilder.setTimerText(timerText);
return pickCallView;
这是我的 PickCallViewBuilder.java
public class PickCallViewBuilder
private CallXML callXML;
private TaxiMapGoogle activity;
private View cellView;
private boolean multiplePickUpTimes = false;
private List<Button> pickUpButtons;
private Button noButton;
public PickCallViewBuilder(CallXML callXML,TaxiMapGoogle activity)
this.callXML = callXML;
this.activity = activity;
definePickUpTimes();
pickUpButtons = new ArrayList<Button>();
createView();
public PickCallViewBuilder setYesButtonListener(OnBidAction onBidAction)
List<TimesPerCallXML> timesPerCallXMLs = callXML.getList();
for(int i=0;timesPerCallXMLs!=null&&i<pickUpButtons.size()&×PerCallXMLs.size()>0;i++)
for(TimesPerCallXML timesPerCallXML:timesPerCallXMLs)
System.out.println("The times per call "+timesPerCallXML.getTimeToPickUp()+" "+timesPerCallXML.getDescription());
PickCallOnClickListener pickCallOnClickListener = new PickCallOnClickListener(
onBidAction,
timesPerCallXMLs.get(i).getTimeToPickUp());
Button pickUpButton = pickUpButtons.get(i);
pickUpButton.setOnClickListener(pickCallOnClickListener);
return this;
public PickCallViewBuilder setNoButtonListener(OnBidAction onBidAction)
if(multiplePickUpTimes)
noButton = (Button) cellView.findViewById(R.id.fifth_button);
else
noButton = (Button) cellView.findViewById(R.id.no_button);
PickCallOnClickListener pickCallOnClickListener = new PickCallOnClickListener(onBidAction,null);
noButton.setOnClickListener(pickCallOnClickListener);
noButton.setVisibility(View.VISIBLE);
return this;
public PickCallViewBuilder setDismissButtonListener(OnClickListener dismissClickListener)
final Button dismissButton = (Button) cellView.findViewById(R.id.dismiss_button);
dismissButton.setOnClickListener(dismissClickListener);
return this;
private void definePickUpTimes()
if(callXML.getList()!=null&&callXML.getList().size()>1)
multiplePickUpTimes = true;
private void createView()
LayoutInflater layoutInflater = activity.getLayoutInflater();
if(multiplePickUpTimes)
cellView = layoutInflater.inflate(R.layout.pick_call_cell_multiple_button, null);
else
cellView = layoutInflater.inflate(R.layout.pick_call_cell, null);
populateFields();
public View getView()
return cellView;
private void populateFields()
LinearLayout pickUpLayout = (LinearLayout) cellView.findViewById(R.id.pickUpLayout);
LinearLayout specialLayout = (LinearLayout) cellView.findViewById(R.id.messageLayout);
LinearLayout distanceLayout = (LinearLayout) cellView.findViewById(R.id.distanceLayout);
LinearLayout destinationLayout = (LinearLayout) cellView.findViewById(R.id.destinationLayout);
LinearLayout fareLayout = (LinearLayout) cellView.findViewById(R.id.fareLayout);
LinearLayout bidLayout = (LinearLayout) cellView.findViewById(R.id.bidLayout);
LinearLayout paymentLayout = (LinearLayout) cellView.findViewById(R.id.paymentLayout);
LinearLayout timerLayout = (LinearLayout) cellView.findViewById(R.id.bidLayout2);
TextView pickUpText = (TextView) pickUpLayout.findViewById(R.id.pickUpLocText);
TextView specialText = (TextView) specialLayout.findViewById(R.id.specialText);
TextView distanceText = (TextView) distanceLayout.findViewById(R.id.distanceText);
TextView destinationText = (TextView) destinationLayout.findViewById(R.id.destinationText);
TextView fareText = (TextView) fareLayout.findViewById(R.id.fareText);
TextView companyText = (TextView) distanceLayout.findViewById(R.id.companyText);
TextView callTypeLayoutText = (TextView) distanceLayout.findViewById(R.id.callTypeLayoutText);
TextView bidText = (TextView) bidLayout.findViewById(R.id.bidText);
TextView paymentText = (TextView) paymentLayout.findViewById(R.id.paymentType);
TextView timerText = (TextView) timerLayout.findViewById(R.id.timer);
setDistance(distanceText);
setAddress(pickUpText, pickUpLayout);
setSpecialNeeds(specialText, specialLayout);
setCompanyText(companyText);
setDestination(destinationText,destinationLayout);
setFare(fareText, fareLayout);
setCallType(callTypeLayoutText);
setPaymentText(paymentText);
setTimerText(timerText);
setPickUpButtons();
public void setTimerText(final TextView timerText)
final int timetoanswer = (callXML.getRequestWaitTime()+callXML.getClearBiddingTime())*1000;
new CountDownTimer(timetoanswer, 1000)
public void onTick(long millisUntilFinished)
if (millisUntilFinished >= (callXML.getRequestWaitTime()+1)*1000)
timerText.setTextColor(activity.getResources().getColor(R.color.biddingtime));
timerText.setText("seconds remaining: " + millisUntilFinished / 1000);
else
timerText.setTextColor(activity.getResources().getColor(R.color.waittime));
timerText.setText("seconds remaining: " + millisUntilFinished / 1000);
public void onFinish()
//timerText.setText("done!");
.start();
private void setDistance(TextView distanceText)
double distanceToPassenger = 0.0;
if(callXML.getDistance()!=null)
try
distanceToPassenger = Double.parseDouble(callXML.getDistance().replaceAll(",", "."));
catch(Exception e)
e.printStackTrace();
else
distanceToPassenger = (double) activity.getDistanceToPoint(
callXML.getLat().doubleValue(),
callXML.getLng().doubleValue());
distanceToPassenger /= 1000;
String measure = getMeasure(distanceToPassenger);
int distanceColour = getDistanceColour(distanceToPassenger);
distanceText.setText(String.valueOf(distanceToPassenger)+" "+measure);
distanceText.setTextColor(distanceColour);
private String getMeasure(double distanceToPassenger)
String measure = null;
if(distanceToPassenger < 1)
measure = activity.getString(R.string.m);
else
measure = activity.getString(R.string.km);
return measure;
private int getDistanceColour(double distanceToPassenger)
int distanceColor;
if(distanceToPassenger < 1)
distanceToPassenger *= 1000;
distanceColor = activity.getResources().getColor(R.color.lesskmcolor);
else
if(distanceToPassenger<2)
distanceColor = activity.getResources().getColor(R.color.lesstwokmcolor);
else
distanceColor = activity.getResources().getColor(R.color.maxkmcolor);
return distanceColor;
private void setAddress(TextView pickUpText,LinearLayout pickUpLayout)
if(callXML.getGaddress()!=null)
pickUpText.setText(callXML.getGaddress());
else
pickUpLayout.setVisibility(View.GONE);
private void setSpecialNeeds(TextView specialText,LinearLayout specialLayout)
if(callXML.getSpecial()!=null)
specialText.setText(callXML.getSpecial());
specialText.setTextColor(activity.getResources().getColor(R.color.deepredcolor));
else
specialLayout.setVisibility(View.GONE);
private void setCompanyText(TextView companyText)
companyText.setText(callXML.getCompanyName()!=null?" - "+callXML.getCompanyName():"");
private void setDestination(TextView destinationText,LinearLayout destinationLayout)
if(callXML.getDestination()!=null)
destinationText.setText(callXML.getDestination());
else
destinationLayout.setVisibility(View.GONE);
private void setFare(TextView fareText,LinearLayout fareLayout)
if(callXML.getFare()!=null&&callXML.getFare()!=0.0)
try
fareText.setText(callXML.getFare().toString()+" "+Currency.getInstance("EUR").getSymbol());
catch(Exception e)
e.printStackTrace();
fareText.setText(callXML.getFare().toString()+" €");
else
fareLayout.setVisibility(View.GONE);
private void setCallType(TextView callTypeLayoutText)
if(callXML.getCallTypeName()!=null)
callTypeLayoutText.setText(" - "+callXML.getCallTypeName());
else
callTypeLayoutText.setVisibility(View.GONE);
private void setPaymentText(TextView paymentText)
if(callXML.getPaymentType()!=null)
String text = paymentTypeString();
paymentText.setText(activity.getString(R.string.payment_type) + text);
else
paymentText.setVisibility(View.GONE);
private void setPickUpButtons()
if(multiplePickUpTimes)
setPickUpTimesButtons();
else
setYesButton();
private void setPickUpTimesButtons()
List<TimesPerCallXML> timesPerCallXMLs = callXML.getList();
for(int i=0;i<timesPerCallXMLs.size();i++)
Button pickUpButton = getPickTimesButton(i);
setUpPickUpButton(pickUpButton,timesPerCallXMLs.get(i));
pickUpButtons.add(pickUpButton);
private void setYesButton()
Button yesButton = (Button) cellView.findViewById(R.id.ok_button);
yesButton.setVisibility(View.VISIBLE);
pickUpButtons.add(yesButton);
private Button getPickTimesButton(int timesPerCall)
Button yesButton;
switch (timesPerCall)
case 0:
yesButton = (Button) cellView.findViewById(R.id.first_button);
break;
case 1:
yesButton = (Button) cellView.findViewById(R.id.second_button);
break;
case 2:
yesButton = (Button) cellView.findViewById(R.id.third_button);
break;
case 3:
yesButton = (Button) cellView.findViewById(R.id.fourth_button);
break;
default:
throw new IllegalArgumentException("an invalid number was provided");
return yesButton;
private void setUpPickUpButton(Button button,TimesPerCallXML timesPerCallXML)
button.setVisibility(View.VISIBLE);
setTimeText(button, timesPerCallXML);
private void setTimeText(Button button,TimesPerCallXML timesPerCallXML)
if(timesPerCallXML.getDescription()!=null)
button.setText(timesPerCallXML.getDescription());
else
button.setText(timesPerCallXML.getTimeToPickUp()+"'");
public abstract class OnBidAction
public abstract void onBid(Integer pickUpTime);
public void setButtonVisibility(int visibility)
cellView.findViewById(R.id.biddingbuttons).setVisibility(View.INVISIBLE);
public class PickCallOnClickListener implements OnClickListener
private OnBidAction onBidAction;
private Integer pickUpTime;
public PickCallOnClickListener(OnBidAction onBidAction,Integer pickUpTime)
this.onBidAction = onBidAction;
this.pickUpTime = pickUpTime;
@Override
public void onClick(View v)
this.onBidAction.onBid(pickUpTime);
private String paymentTypeString()
String paymentStr = callXML.getPaymentType();
PaymentType paymentType = null;
try
paymentType = PaymentType.valueOf(paymentStr);
catch(Exception e)
AploonLogger.error("Invalid payment type ", e);
return paymentStr;
switch (paymentType)
case cash:
return activity.getString(R.string.cash_payment_type);
case ccard:
return activity.getString(R.string.ccard_payment_type);
case credit:
return activity.getString(R.string.credit_payment_type);
case epayment:
return activity.getString(R.string.epayment_payment_type);
default:
return paymentStr;
我的 CallXML.java
公共类 CallXML
public static final String LOG_ERR_TAG = "PARSE";
public static final String INFO_ROOT_CALL_ELEMENT = "tripInfo";
public static final String OLD_ROOT_CALL_ELEMENT = "Call";
public static final String ROOT_CALL_ELEMENT = "PlaceCall";
public static final String ROOT_ASSIGNMENT_ELEMENT = "AssignmentConfirmation";
public static final String CONTENT_ELEMENT = "content";
public static final String ROOT_TYPE_ELEMENTS = "TimesPerCalls";
public static final String ROOT_TYPE_ELEMENT = "TimesPerCall";
private boolean pickedUpCall = false;
private boolean pickedUpPassenger = false;
private Long taxiCompanyId;
private String action;//required
private Integer id; //required
private BigDecimal lat;
private BigDecimal lng;
private String address;
private String gaddress;
private String name;
private Timestamp regtime;
private String special;
private String status;
private String destination;
private String gender;
private String mobile;
private String messageFromServer;
private String driverImei;
private String plateno;
private String deviceId;
private String distance;
private String remarks;
private String companyName;
private Double fare=0.0;
private String paymenttype;
private String transactionToken;
private String zoneId;
private String zonePosition;
private String callTypeName;
private Integer clearBiddingTime;
private Integer requestWaitTime;
private List<TimesPerCallXML> timesPerCallList;
public String toString()
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
return (regtime != null? " [" + sdf.format(regtime) + "] " : "") +
" Address: " + getFormattedAddress() +
(name != null? " Name: " + name + " " : "") +
(special != null? " Special needs: " + special + " " : "");
public String getFormattedAddress()
return String.format("%s", address == null? gaddress : address);
public void update(String address, String gaddress, String special, String destination)
setAddress(address);
setGaddress(gaddress);
setSpecial(special);
setDestination(destination);
public String getFormattedCompanyName()
return companyName != null? "(" + companyName + ")" : "";
/**
* This is a helper method to pass directly the String value as it comes from the XML.
* @param fieldName
* @param value
* @throws Exception
*/
public void setField(String fieldName, Object value) throws Exception
if(!value.toString().equals("null") && !value.toString().equals("(null)"))
if (fieldName.equals("id"))
id = Integer.parseInt((String) value);
else if(fieldName.equals("taxiCompanyId"))
taxiCompanyId = Long.parseLong((String) value);
else if (fieldName.equals("action"))
action = (String) value;
else if (fieldName.equals("address"))
address = (String) value;
else if (fieldName.equals("gaddress"))
gaddress = (String) value;
else if (fieldName.equals("name"))
name = (String) value;
else if (fieldName.equals("regtime"))
try
regtime = value != null? new Timestamp(Long.parseLong((String) value)) : null;
catch(Exception e)
Log.e(LOG_ERR_TAG, "Failed to parse Regtime returned in the Call context due to exception: " + e.getMessage());
else if (fieldName.equals("lat"))
try
lat = new BigDecimal(((String) value).replace(',', '.'));
catch(Exception e)
Log.e(LOG_ERR_TAG, "Failed to parse Latitude returned in the Call context due to exception: " + e.getMessage());
else if (fieldName.equals("lng"))
try
lng = new BigDecimal(((String) value).replace(',', '.'));
catch(Exception e)
Log.e(LOG_ERR_TAG, "Failed to parse Longitude returned in the Call context due to exception: " + e.getMessage());
else if (fieldName.equals("special"))
special = (String) value;
else if (fieldName.equals("status"))
status = (String) value;
if("act".equals(status))
pickedUpPassenger = true;
else if (fieldName.equals("destination"))
destination = (String) value;
else if (fieldName.equals("gender"))
gender = (String) value;
else if (fieldName.equals("mobile"))
mobile = (String) value;
else if (fieldName.equals("msg"))
messageFromServer = (String) value;
else if (fieldName.equals("driverImei"))
driverImei = (String) value;
else if (fieldName.equals("deviceId"))
deviceId = (String) value;
else if (fieldName.equals("plateno"))
plateno = (String) value;
else if (fieldName.equals("distance"))
distance = (String) value;
else if (fieldName.equals("remarks"))
remarks = (String) value;
else if (fieldName.equals("companyname"))
companyName = (String) value;
else if(fieldName.equals("callTypeName"))
callTypeName = (String) value;
else if (fieldName.equals("paymenttype"))
paymenttype =(String) value;
else if (fieldName.equals("fare"))
fare = Double.parseDouble((String) value);
else if (fieldName.equals("transactionToken"))
transactionToken = (String) value;
else if (fieldName.equals("zoneId"))
zoneId = (String) value;
else if (fieldName.equals("zonePosition"))
zonePosition = (String) value;
else if(fieldName.equals("clearBiddingTime"))
clearBiddingTime = Integer.valueOf((String) value);
else if(fieldName.equals("requestWaitTime"))
requestWaitTime = Integer.valueOf((String) value);
public Long getTaxiCompanyId()
return taxiCompanyId;
public void setTaxiCompanyId(Long taxiCompanyId)
this.taxiCompanyId = taxiCompanyId;
/**
* Address provided (if any) by the customer during request.
* @return
*/
public String getAddress()
return address;
public void setAddress(String address)
this.address = address;
/**
* Address determined by the Google location service based upon coordinates automatically provided by customer's GPS enabled device.
* This address should be more precise over the one provided by customer.
* @return
*/
public String getGaddress()
return gaddress;
public void setGaddress(String gaddress)
this.gaddress = gaddress;
public String getName()
return name;
public void setName(String name)
this.name = name;
public Timestamp getRegtime()
return regtime;
public void setRegtime(Timestamp regtime)
this.regtime = regtime;
public String getSpecial()
return special;
public void setSpecial(String special)
this.special = special;
public String getAction()
return action;
public void setAction(String action)
this.action = action;
public Integer getId()
return id;
public void setId(Integer id)
this.id = id;
public BigDecimal getLat()
return lat;
public void setLat(BigDecimal lat)
this.lat = lat;
public BigDecimal getLng()
return lng;
public void setLng(BigDecimal lng)
this.lng = lng;
public String getDestination()
return destination;
public void setDestination(String destination)
this.destination = destination;
public String getGender()
return gender;
public void setGender(String gender)
this.gender = gender;
public String getMobile()
return mobile;
public void setMobile(String mobile)
this.mobile = mobile;
public String getMessageFromServer()
return messageFromServer;
public void setMessageFromServer(String messageFromServer)
this.messageFromServer = messageFromServer;
public String getDriverImei()
return driverImei;
public void setDriverImei(String driverImei)
this.driverImei = driverImei;
public String getPlateno()
return plateno;
public void setPlateno(String plateno)
this.plateno = plateno;
public boolean isPickedUpCall()
return pickedUpCall;
public void setPickedUpCall(boolean pickedUpCall)
this.pickedUpCall = pickedUpCall;
public boolean isPickedUpPassenger()
return pickedUpPassenger;
public void setPickedUpPassenger(boolean pickedUpPassenger)
this.pickedUpPassenger = pickedUpPassenger;
public String getDeviceId()
return deviceId;
public void setDeviceId(String deviceId)
this.deviceId = deviceId;
public String getDistance()
return distance;
public void setDistance(String distance)
this.distance = distance;
public String getRemarks()
return remarks;
public void setRemarks(String remarks)
this.remarks = remarks;
public String getStatus()
return status;
public void setStatus(String status)
this.status = status;
public String getCompanyName()
return companyName;
public void setCompanyName(String companyName)
this.companyName = companyName;
public Double getFare()
return fare;
public String getPaymentType()
return paymenttype;
public String getTransactionToken()
return transactionToken;
public String getCallTypeName()
return callTypeName;
public void setCallTypeName(String callTypeName)
this.callTypeName = callTypeName;
public String getZoneId()
return zoneId;
public void setZoneId(String zoneId)
this.zoneId = zoneId;
public String getZonePosition()
return zonePosition;
public void setZonePosition(String zonePosition)
this.zonePosition = zonePosition;
public void setList(List<TimesPerCallXML> list)
this.timesPerCallList = list;
public List<TimesPerCallXML> getList()
return timesPerCallList;
public Integer getClearBiddingTime()
return clearBiddingTime;
public void setClearBiddingTime(Integer clearBiddingTime)
this.clearBiddingTime = clearBiddingTime;
public Integer getRequestWaitTime()
return requestWaitTime;
public void setRequestWaitTime(Integer requestWaitTime)
this.requestWaitTime = requestWaitTime;
【问题讨论】:
每次单元格变得可见时都会调用适配器的getView。因此,如果您在每次调用 getView 时都构建一个新单元格,则该单元格将有一个新的倒计时。您必须将当前的倒计时状态保存在单元格之外的其他位置。 您能否提供一个示例,说明您使用某些代码的意思?谢谢! 【参考方案1】:在这部分:
public void setTimerText(final TextView timerText)
final int timetoanswer = (callXML.getRequestWaitTime()+callXML.getClearBiddingTime())*1000;
new CountDownTimer(timetoanswer, 1000)
public void onTick(long millisUntilFinished)
if (millisUntilFinished >= (callXML.getRequestWaitTime()+1)*1000)
timerText.setTextColor(activity.getResources().getColor(R.color.biddingtime));
timerText.setText("seconds remaining: " + millisUntilFinished / 1000);
else
timerText.setTextColor(activity.getResources().getColor(R.color.waittime));
timerText.setText("seconds remaining: " + millisUntilFinished / 1000);
public void onFinish()
//timerText.setText("done!");
.start();
在onTick()
的每次迭代中,您都可以将新值存储到您的callXML
。比如:
callXML.setRequestWaitTime(int time);
编辑:将您的 onTick()
部分更改为:
public void onTick(long millisUntilFinished)
if (millisUntilFinished >= (callXML.getRequestWaitTime()+1)*1000)
timerText.setTextColor(activity.getResources().getColor(R.color.biddingtime));
timerText.setText("seconds remaining: " + millisUntilFinished / 1000);
callXML.setClearBiddingTime(callXML.getClearBiddingTime()-1);
else
timerText.setTextColor(activity.getResources().getColor(R.color.waittime));
timerText.setText("seconds remaining: " + millisUntilFinished / 1000);
callXML.setRequestWaitTime(callXML.getRequestWaitTime()-1);
【讨论】:
对不起,我是新手,你能不能给我一个更详细的 callXML.setRequestWaitTime(int time);应该如何?提前谢谢 我不知道你的 CallXML 对象是什么。是你的班级还是来自任何图书馆?你可以在这里发布CallXML类吗? 它现在不是从计时器开始而是显示错误的时间,我认为这是因为它不应该调用 callXML.setRequestWaitTime(callXML.getRequestWaitTime()-1);因为我需要的时间是 RequestWaitTime+ClearBiddingTime 的总和。那么我应该创建一个新的 callXML.setSumTime(time) 吗? 不,等等,我错了,把我的两行换成对方 不是从头开始显示时间错误以上是关于在列表视图中添加倒数计时器会在每个新行中重新启动的主要内容,如果未能解决你的问题,请参考以下文章