Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CodePath Android with Deonna: Week 3, Unit 3 - Twitter Part 1

CodePath Android with Deonna: Week 3, Unit 3 - Twitter Part 1

Deonna Hodges

October 03, 2020
Tweet

More Decks by Deonna Hodges

Other Decks in Programming

Transcript

  1. Debugging lab Twitter Part 1: Concepts what will we cover?

    Breakout rooms Quick break Wisdom from Dr. Jorts
  2. How do we make requests in such a way to

    allow the user to pull down on their timeline and see new tweets? Pull to Refresh Users can sign in using their existing Twitter accounts and see content unique to their account OAuth Users can view tweets from their home timeline. How do we make authenticated API requests to get this data? Networking twitter: user stories
  3. OAuth Authorization (walkthrough) https://www.youtube.com/playlist?list=PLrT2tZ9JRrf7P-WthrcGXm98VTL5VObpn // LoginActivity.java // Click handler for

    the button used to start OAuth flow // Uses the client to initiate OAuth authorization // This should be tied to a button used to login public void loginToRest(View view) { getClient().connect(); }
  4. Defining REST API calls (walkthrough) https://www.youtube.com/playlist?list=PLrT2tZ9JRrf7P-WthrcGXm98VTL5VObpn // RestClient.java // Define

    your Twitter API calls here. public void getInterestingnessList(JsonHttpResponseHandler handler) { String apiUrl = getApiUrl(<unrelated flickr API url>); RequestParams params = new RequestParams(); params.put("format", "json"); client.get(apiUrl, params, handler); }
  5. getHomeTimeline() // RestClient.java public void getHomeTimeline(int sinceId, JsonHttpResponseHandler handler) {

    String apiUrl = getApiUrl("statuses/home_timeline.json"); RequestParams params = new RequestParams(); params.put("since_id", 1); getClient().get(apiUrl, params, handler); } GET https://api.twitter.com/1.1/statuses/home_timeline.json&since_id=1
  6. Defining Data Models { "created_at": "Wed Oct 10 20:19:24 +0000

    2018", "id": 1050118621198921728, "text": "To make room for more expression, we will now count all emojis as equal—including those with gender and skin t… https://t.co/MkGjXf9aXm", "entities": { "hashtags": [], "symbols": [], "user_mentions": [], "urls": [{ "url": "https://t.co/MkGjXf9aXm", "expanded_url": "https://twitter.com/i/web/status/1050118621198921728", "display_url": "twitter.com/i/web/status/1…", "indices": [117,140] }] }, "user": { "id": 6253282, "name": "Twitter API", "screen_name": "TwitterAPI", "verified": true, "profile_image_url_https": "https://pbs.twimg.com/profile_images/942858479592554497/BbazLO9L_normal.jpg", }, "retweet_count": 161, "favorite_count": 296, "favorited": false, "retweeted": false } https://developer.twitter.com/en/docs/twitter-api/v1/data-dictionary/overview/intro-to-tweet-json
  7. Calling getHomeTimeline() RestClient client = RestApplication.getRestClient(this); client.getHomeTimeline(1, new JsonHttpResponseHandler() {

    @Override public void onSuccess(int statusCode, Header[] headers, JSONArray response) { // Parse JSON response into a list of Tweet objects you can use in your RecyclerView List<Tweet> tweets = Tweet.fromJsonMultiple(response); callback.onTweetsReceived(tweets); } @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) { // Figure out why the request failed - you can log, print error messages, etc. callback.onTweetsReceivedError(); } }; )
  8. Parsing a single Tweet { "created_at": "Wed Oct 10 20:19:24

    +0000 2018", "id": 1050118621198921728, "text": "To make room for more expression,… https://t.co/MkGjXf9aXm", "user": { "id": 6253282, "name": "Twitter API", "screen_name": "TwitterAPI", "verified": true, "profile_image_url_https": "https://pbs.twimg.com/profile_images/942858479 592554497/BbazLO9L_normal.jpg", } } public class Tweet { public String createdAt; public String text; public User user; public static Tweet fromJson(JSONObject o) { try { Tweet tweet = new Tweet(); tweet.createdAt = o.getString("created_at"); tweet.text = o.getString("text"); tweet.user = User.parseJSON(o.getJSONObject("user")); return tweet; } catch (JSONException e) { // Debug exception here. } } }
  9. POSTing a new Tweet https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-update // RestClient.java public void postTweet(String

    body, JsonHttpResponseHandler handler) { String apiUrl = getApiUrl("statuses/update.json"); RequestParams params = new RequestParams(); params.put("status", body); getClient().post(apiUrl, params, handler); }
  10. RecyclerView: Setup class TimelineActivity extends AppCompatActivity { private ArrayList<Tweet> tweets

    = new ArrayList<>(); RestClient client = RestApplication.getRestClient(this); @Override protected void onCreate(Bundle savedInstanceState) { //... RecyclerView rvTweets = (RecyclerView) findViewById(R.id.rvTweets); TweetsAdapter adapter = new TweetsAdapter(tweets); rvTweets.setAdapter(adapter); rvTweets.setLayoutManager(new LinearLayoutManager(this)); client.getHomeTimeline(1, new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONArray response) { tweets.addAll(Tweet.fromJsonMultiple(response)); adapter.notifyDataSetChanged(); } } } }
  11. RecyclerView: Fetch Data class TimelineActivity extends AppCompatActivity { private ArrayList<Tweet>

    tweets = new ArrayList<>(); RestClient client = RestApplication.getRestClient(this); @Override protected void onCreate(Bundle savedInstanceState) { //... RecyclerView rvTweets = (RecyclerView) findViewById(R.id.rvTweets); TweetsAdapter adapter = new TweetsAdapter(tweets); rvTweets.setAdapter(adapter); rvTweets.setLayoutManager(new LinearLayoutManager(this)); client.getHomeTimeline(1, new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONArray response) { tweets.addAll(Tweet.fromJsonMultiple(response)); adapter.notifyDataSetChanged(); } } } }
  12. RecyclerView: Populate Data Object class TimelineActivity extends AppCompatActivity { private

    ArrayList<Tweet> tweets = new ArrayList<>(); RestClient client = RestApplication.getRestClient(this); @Override protected void onCreate(Bundle savedInstanceState) { //... RecyclerView rvTweets = (RecyclerView) findViewById(R.id.rvTweets); TweetsAdapter adapter = new TweetsAdapter(tweets); rvTweets.setAdapter(adapter); rvTweets.setLayoutManager(new LinearLayoutManager(this)); client.getHomeTimeline(1, new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONArray response) { tweets.addAll(Tweet.fromJsonMultiple(response)); adapter.notifyDataSetChanged(); } } } }
  13. RecyclerView: Notify Adapter class TimelineActivity extends AppCompatActivity { private ArrayList<Tweet>

    tweets = new ArrayList<>(); RestClient client = RestApplication.getRestClient(this); @Override protected void onCreate(Bundle savedInstanceState) { //... RecyclerView rvTweets = (RecyclerView) findViewById(R.id.rvTweets); TweetsAdapter adapter = new TweetsAdapter(tweets); rvTweets.setAdapter(adapter); rvTweets.setLayoutManager(new LinearLayoutManager(this)); client.getHomeTimeline(1, new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONArray response) { tweets.addAll(Tweet.fromJsonMultiple(response)); adapter.notifyDataSetChanged(); } } } }
  14. Pull to Refresh Step 1: SwipeRefreshLayout XML https://guides.codepath.com/android/implementing-pull-to-refresh-guide <androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/swipeContainer" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rvTweets" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" /> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
  15. Pull to Refresh Step 2: Update RecyclerView Adapter https://guides.codepath.com/android/implementing-pull-to-refresh-guide //

    In the RecyclerView.Adapter class // Clear the data public void clear() { items.clear(); notifyDataSetChanged(); } // Add a list of updated items public void addAll(List<Tweet> list) { items.addAll(list); notifyDataSetChanged(); }
  16. Pull to Refresh Step 3: Hook up SwipeRefreshLayout https://guides.codepath.com/android/implementing-pull-to-refresh-guide public

    class TimelineActivity extends Activity { private SwipeRefreshLayout swipeContainer; @Override protected void onCreate(Bundle savedInstanceState) { //... swipeContainer = (SwipeRefreshLayout) findViewById(R.id.swipeContainer); // Setup refresh listener which triggers new data loading swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { // Method to refresh the list fetchTimelineAsync(1); } }); } public void fetchTimelineAsync(int sinceId) { // Send the network request to fetch the updated data client.getHomeTimeline(sinceId, new JsonHttpResponseHandler() { public void onSuccess(JSONArray json) { adapter.clear(); adapter.addAll(Tweet.fromJsonMultiple(json)); // Remember to call setRefreshing(false) to signal refresh has finished swipeContainer.setRefreshing(false); } }); } }
  17. breakout rooms what new habits / hobbies have you gotten

    into in 2020 that you want to continue? what is your favorite app? how would you improve it? if you could be a kitchen appliance what would you be? what was the last truly great show you’ve watched or book you’ve read? android or iOS?