Advertisement
Guest User

help

a guest
Mar 21st, 2019
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.40 KB | None | 0 0
  1. 1 Design rationale
  2. 1.1 Initial load
  3. For the app to do anything useful, it first had to load some data from the NewsAPI endpoint. There were a number of different ways I could do this whilst still providing a good user experience, one of which was loading a particular category feed’s data, displaying that to the user, and then sending off requests for the other categories. However, I decided that this could cause too many issues if the user opened the app then quickly navigated to different categories whilst on a slow connection. I decided the best course of action was to simply load data for every category upon launching the app whilst displaying a ”Loading...” spinner to the user. Whilst this meant there was some user downtime whilst they waited for the app to launch, it guaranteed that they could browse easily once past that stage.
  4. 1.2 Main activity
  5. There were several ways I could have laid out the main news feeds activity whilst still meeting the specification. I could have provided some kind of drop-down selection box for filtering categories - this would integrate nicely with a free text search engine - or some other form of selection UI. I settled on a ViewPager + TabLayout combination with each view displaying a news feed fragment for a particular category. Not only is this how other similar apps - such as the official BBC News app - operate, but it makes quickly and easily navigating through categories a breeze; the user can either lazily swipe through the different feeds, or scroll the tab bar to click on a particular topic.
  6. 1.3 News feeds
  7. Despite the many different ways of displaying lists in Android, there was no doubt in my mind that RecyclerViews would function best for my app and its data. RecyclerViews allow for efficient ”infinite scrolling” lists, and offer the developer a great deal of control over the implementation thanks to the Adapters tied to each view.
  8. 1.4 Data storage
  9. A few different data storage options were available to me. Android provides good support for SQLite, so I decided to implement a typical SQLite database system with a singleton helper class acting as the middleman between the database and any methods wishing to access it. Other than text file storage formats such as .csv - less than ideal for my app due to how frequently its data is updated or removed - the only other real option was Room, an Android-specific abstraction layer over SQLite. Although there are benefits to Room over raw SQLite, such as its compile-time
  10. 1
  11. verification of SQL queries, I chose the latter simply because I was more familiar with developing with it.
  12. 1.5 Threading
  13. There are many different ways to multithread Android applications. As long as the developer follows the two golden rules - do not block the UI thread, and do not access the UI from outside the UI thread - it’s up to them how they implement parallelism. I chose to use AsyncTasks for all of my parallel work since they provide a quick-to-set-up, effective, and flexible way to take tasks off of the main thread whilst still being able to post results to the UI. My API requests were also carried out on separate threads with Android’s Volley library; I used a mixture of callbacks and promises to process responses asynchronously and synchronously respectively.
  14. 1.6 Layout
  15. Although there is an argument to be made for keeping layouts as simple as possible, I chose to use the relatively heavyweight ConstraintLayout for every single one of my layout XML files. The ability to specify the positions and sizes of views relative to their parents and siblings hugely simplifies the universal UI design process; in my mind, there’s no alternative worth considering.
  16. 2 Key app components
  17. 2.1 InitialLoadActivity
  18. This is the main activity of my app. Its UI is simply some text and a progress spinner, but it’s responsible for the initial population of the database with news data. Once it’s finished fetching data, it immediately starts the FeedActivity. Crucially, it also has its noHistory value set to true in the Android manifest, meaning the activity is taken off the backstack when it is stopped.
  19. 2.2 FeedActivity, ViewPager, TabLayout, and CategorisedFeedFragments
  20. FeedActivity is the primary activity the user sees whilst using the app. It contains a ViewPager + TabLayout combination which holds a Fragment for each news feed topic and allows users to swipe through them. CategorisedFeedFragments are the primary point of interaction for the user. They contain news feeds for different topics, and allow users to do things like refresh, select, and scroll through stories.
  21. 2.3 DatabaseHelper
  22. This middleman class is the gateway to database interaction in my app. Containing methods for inserting into, deleting from, and querying the database, it means other classes don’t need to worry about SQL or proper database management. It publicises general app-level methods, such as initial data population and loading a table into the news feed, whereas it keeps its more direct methods for CRUD operations at the package level, allowing the AsyncTask classes to access them.
  23. 2.4 RequestQueueHandler
  24. Similar to DatabaseHelper, this class acts as an intermediary, except to the Volley request service, sending off asynchronous HTTP requests to the news API.
  25. 2
  26. 2.5 AsyncTask classes
  27. These each perform specific data-related actions carried out off of the UI thread, typically involving fetching data from the API, storing it in the database, and sending it to the news feeds’ adapters. Since some elements of these operations require serial execution, some HTTP requests are carried out using ’promises’, which block the executing thread until a request is received, as opposed to the more typical asynchronous callback functions.
  28. 3 Additional features
  29. My app adds two extra features on top of the specification.
  30. 3.1 Blacklist
  31. By long pressing an item in the news feed, users are able to blacklist sources to prevent them from ever showing up in their feeds. Users can view and edit their blacklist through the FeedActivity’s options menu. The implementation is very straightforward: the names of blacklisted sources are stored in shared preferences, and any AsyncTask which publishes data to an adapter first filters its results against this blacklist.
  32. 3.2 Favourites list
  33. Much more complex is the favourites list. As well as the topic categories, users have access to a ’favourites’ tab in their FeedActivity, which only displays news stories from sources which have been previously ’favourited’; like with the blacklist, this is done though long pressing a story. At first, this seems like it should be simple: since NewsAPI’s ’top stories’ endpoint allows you to filter by source IDs, all one must do is save the IDs of favourited sources in shared preferences to request with. However, not only do most sources from NewsAPI not have a defined source ID, but there is no other way to filter sources (e.g. by source name) at the endpoint level. The way I chose to address this was to make the fetching of favourite news stories a two-stage operation: first, a ID-filtered request is made to the endpoint; then, a general ’top stories’ request is made. The response to the latter request is then filtered to eliminate any non-favourited sources, before being combined with the first response, sorted reverse-chronologically, and published to the display adapters. Unfortunately, this solution means that favourited sources without IDs often don’t appear in the feed at all. Still, it does guarantee that the favourites tab will always contain news from sources the user has favourited whilst permitting the user to favourite any source they see.
  34. 4 Reflection
  35. 4.1 Planning
  36. My development process was significantly under-planned, primarily due to my lack of experience in creating large-scale Android apps. I adopted a Big Bang development model approach, fully intending to come across - and learn from - a multitude of issues whilst developing; however, some time spent formally planning would definitely have proved useful in keeping myself on course and reducing overall development time. Now that I have a significantly greater understanding of things
  37. 3
  38. such as threading strategies and universal UI design, I will be much better equipped to plan any future Android development projects I undertake.
  39. 4.2 Design
  40. Unlike my planning, I am very happy with my design, both in terms of UI and program structure. Although it took a while to fully coalesce, my design followed the key tenets of app design: the user experience is smooth, the user interface is ergonomic, background tasks are executed invisible to the user, and the app is resilient against unpredictable user input.
  41. 4.3 Development
  42. Although the lack of planning certainly played a part, the main obstacle to smooth development was my inexperience of developing for a multithreaded, input-rich environment. I constantly encountered bugs due to race conditions and unexpected user interactions, and it took me a long while to fully grasp how the flow of execution in my app would play out. Once I got over that hurdle, development became much smoother and I was more easily able to build the app’s components and classes to be tailor fit for purpose.
  43. 4.4 Knowledge gained
  44. This project has been immeasurably useful for my app development knowledge and skills. With each new feature I implemented, challenges would be raised, demanding research and careful thought. In particular, my ability to write safe multithreaded code has greatly improved thanks to this project.
  45. 4.5 Possible improvements
  46. My first improvement would be on the favouriting feature; although it would require a lot of work, there are definitely ways of making it so a more even distribution of favourited sources appear in the favourites feed. Another useful improvement that would require research and some careful design would be to enhance my cache strategy, particularly with images. Currently, my app caches images directly to memory through an LruCache. However, since main memory is limited, the number of images that can be stored locally at once is low, meaning my app needs to make a lot of image fetch requests. This is a problem if the device’s internet connection isn’t stable or is lost entirely. Simply storing all images downloaded into some form of secondary storage isn’t a viable solution due to the memory footprint, but perhaps some kind of paging system could improve performance without consuming too much device storage space.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement