import UIKit
let encrouragement = "You can do it!"
var personalizedEncouragement = "You can do it, Lauren!"
personalizedEncouragement = personalizedEncouragement.stringByReplacingOccurrencesOfString("Lauren", withString:"Cameron")
let birthYear = 2008
var currentYear == 2017
var age = currentYear - birthYear
let buildingCapacity = 300
var attendance = 220
attendance += 2
var goat = UIImage(named:"Chinese-New-Year-3.jpg")!
let yearsOfTheGoat = [1967, 1979, 1991, 2003, 2015]
let yearsOfTheSheep = [1967, 1979, 1991, 2003, 2015]
yearsOfGoat.append(2027)
String
import UIKit import Foundation var funWithStrings = UIImage(named:"kittenWithOrangeString.jpg"): let myFirstString = "no " let mySecondString = "no problems" let theTruth = myFirstString + ", " + mySecondString var doggyDiet = "Lulu eats 25lbs of dog food per month" var dogName = "Ferris" var ferrisPic = UIImage(named:"SpringerdoodleFerris.jpg")
var lbsPerDay = 0.75 var daysPerMonth:Double = 30.0 doggyDiet = "\(dogName) eats \(lbsPerDay * daysPerMonth) of dog food per month" var frankiePic = UIImage(named:"frankie.jpeg")! lbsPerDay = 0.25 dogName = "Lil Frankie" doggyDiet = "\(dogName) eats \(lbsPerDay * daysPerMonth) of dog food per month"
access an array of characters
var password = "Meet me in St. Louis"
for character in password.characters {
if character == "e" {
print("found an e!")
} else {
}
}
if else
if hungry && !vegetarian {
println("Let's eat steak!")
} else if hungry && vegetarian {
println("How about pumpkin curry?")
} else {
println("nevermind")
}
var thereIsPie = true
if hungry || thereIsPie {
println("Let's eat!")
} else {
println("Let's wait.")
}
Ternary conditional
if question {
answer1
} else {
answer2
}
hugry ? println("Let's eat!") : println("Let's wait.")
hugry || thereIsPie ? println("Let's eat!") : println("Let's wait.")
Swift types
import UIKit
import Foundation
class LightSwitch {
var on: Bool = true
}
var livingRoomSwitch = LightSwitch()
livingRoomSwitch.on
var dollarSign: Character = "$" var myFirstSwiftString String = "no' money"
Optional and Tuples
let kitchenSwitch = LightSwitch()
let ticketPrice = 13.75
let swiftIsFast = true
let encouragement = “You can do it!”
let ticketPrice = 7.5
let allowance = 10.0
var iceCreamPrice = 3.0
var pic UIImage(named:"Choe.png")!
if allowance >= ticketPrice + iceCreamPrice {
println("Let's go to the movies!")
} else {
println("Let's watch a movie at home and eat ice cream")
}
var hungry = true
var vegetarian = false
if hungry {
println("Let's eat!")
} else {
println("Let's wait.")
}
Verify Loader Behavior
add log message to
initLoader(), onCreateLoader() callback, Loader startLoading()method
onLoadFinished() callback, Loader loadInBackground() method
onLoaderReset() callback, queryUtils fetchEarthquakeData() method
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/list" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="@null" android:dividerHeight="0dp"/> <TextView android:id="@+id/empty_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textAppearance="?android:textAppearanceMedium"/> </RelativeLayout>
private TextView mEmptyStateTextView;
@Override
protected void onCreate(Bundle savedInstanceState){
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
earthquakeListView.setEmptyView(mEmptyStateTextView);
}
@Override
public void onLoadFinished(Loader<List<Earthquake>> loader, List<Earthquake> earthquakes){
mEmptyStateTextView.setText(R.string.no_earthquakes);
}
Async Task In Quake Report App
private class EarthquakeAsyncTask extends
AsyncTask<String, Void, List<Earthquake>>{
...
}
https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&eventtype=earthquake&orderby=time&minmag=6&limit=10
Loader
https://developer.android.com/guide/components/loaders.html?utm_source=udacity&utm_medium=course&utm_campaign=android_basics
Loader manager
https://developer.android.com/reference/android/app/LoaderManager.html?utm_source=udacity&utm_medium=course&utm_campaign=android_basics
Loader callback
https://developer.android.com/reference/android/app/LoaderManager.LoaderCallbacks.html?utm_source=udacity&utm_medium=course&utm_campaign=android_basics
package com.example.android.quakereport;
import android.content.AsyncTaskLoader;
import android.content.Context;
import java.util.List;
public class EarthquakeLoader extends AsyncTaskLoader<List<Earthquake>>{
private static final String LOG_TAG = EarthquakeLoader.class.getName();
private String mUrl;
public EarthquakeLoader(Context context, String url){
super(context);
mUrl = url;
}
@Override
protected void onStartLoading(){
forceLoad();
}
@Override
public List<Earthquake> loadInBackground(){
if (mUrl == null){
return null;
}
List<Earthquake> earthquakes = QueryUtils.fetchEarthquakeData(mUrl);
return earthquakes;
}
}
Handle Empty or Null Cases
protected Event doInBackground(String... urls){
if (urls.length < 1 || urls[0] == null){
return null;
}
Event result = Utils.fetchEarthquakeData(urls[0]);
return result;
}
protected void onPostExecute(Event result){
if (result == null){
return;
}
updateUi(result);
}
private class EarthquakeAsyncTask extends AsyncTask{ protected Event doInBackground(String... urls){ if (urls.length < 1 || urls[0] == null){ return null; } Event result = Utils.fetchEarthquakeData(urls[0]); return result; } protected void onPostExecute(Event result){ if (result == null){ return; } updateUi(result); } }
Asynctask callback methods
onPreExecute(): before the task is executed, Main
doInBackground(Params…): After onPreExecute, Background
onProgressUpdate(Progress…): After publishProgress() is called, while doInBackground is executing, Main
OnPostExecute(Result): After doInBackground() finishes, Main
Review of generics
ArrayList
add(E e)->requires object of type E as input
get(int index)->returns object of type E
ArrayAdapter
private class DownloadFileTask extends AsyncTask{ protected Long doInBackground(RUL... urls){ int count = urls.length; long totalSize = 0; for(int i = 0; i < count; i++){ totalSize += Downloader.downloadFile(url[i]); publishProgress((int)((i/(float) count)* 100)); if(isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress){ setProgressPercent(progress[0]); } protected void onPostExecute(long result){ showDialog("Downloaded " + result + " bytes"); } }
private class DownloadWebpageTask extends AsyncTask<String, Void, String>{
@Override
protected String doInBackground(String... urls){
try {
return downloadUrl(urls[0]);
} catch (IOException e){
return "Unable to retrieve web page. URL may be invalid.";
}
}
@Override
protected void onPostExecute(String result){
textView.setText(result);
}
}
Main Thread vs Background Thread
Background Thread(In) -> Perform Network Request -> Out
Main Thread(In) -> Click Button -> Out
Asynctask to the rescue
Async -> 非同期
https://developer.android.com/reference/android/os/AsyncTask.html
private class DownloadFilesTask extends AsyncTask{ protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }
concrete class
abstract class
interface
public class Main Activity extends Activity {
onCreate(){
}
onCreate(){
}
}
public class EarthquakeAsyncTask extends AsyncTask {
doInBackground(){
}
}
Threads & Parallelism
Event.java
package com.example.android.didyoufeelit;
public class Event {
public final String title;
public final String numOfPeople;
public final String perceivedStrength;
public Event(String eventTitle, String eventNumOfPeople, String eventPerceivedStrength){
title = eventTitle;
numOfPeople = eventNumOfPeople;
perceivedStrength = eventPerceivedStrength;
}
}
package com.example.android.didyoufeelit;
import android.os.Bundle;
import android.support.v7.app.AppCompactActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private static final String USGS_REQUEST_URL =
"http://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2016-01-01&endtime=2016-05-02&minfelt=50&minmagnitude=5";
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Event earthquake = Utils.fetchEarthquakeData(USGS_REQUEST_URL);
updateUi(eqrthquake);
}
private void updateUi(Event earthquake){
TextView titleTextView = (TextView) findViewById(R.id.title);
titleTextView.setText(earthquake.title);
TextView tsunamiTextView = (TextView) findViewById(R.id.number_of_people);
tsunamitextView.setText(getString(R.string.num_people_felt_it, earthquake.numOfPeople));
TextView magnitudeTextView = (TextView) findViewById(R.id.perceive_magnitude);
magnitudeTextView.setText(earthquake.perceivedStrength);
}
}