When programming in groups of people, it s essential to version the code. One of the most popular versioning tools is git. Some benefits of git are:

Similar documents
Upon completion of the second part of the lab the students will have:

Creating a Custom ListView

ListView (link) An ordered collection of selectable choices. key attributes in XML:

Android App Development. Mr. Michaud ICE Programs Georgia Institute of Technology

INTRODUCTION COS MOBILE DEVELOPMENT WHAT IS ANDROID CORE OS. 6-Android Basics.key - February 21, Linux-based.

Agenda. Overview of Xamarin and Xamarin.Android Xamarin.Android fundamentals Creating a detail screen

Creating a User Interface

Android UI Development

Fragments. Lecture 11

Android development. Outline. Android Studio. Setting up Android Studio. 1. Set up Android Studio. Tiberiu Vilcu. 2.

ListView Containers. Resources. Creating a ListView

Mobile Programming Lecture 2. Layouts, Widgets, Toasts, and Event Handling

Hello World. Lesson 1. Android Developer Fundamentals. Android Developer Fundamentals. Layouts, and. NonCommercial

Developing Android Applications Introduction to Software Engineering Fall Updated 1st November 2015

GUI Widget. Lecture6

CS 370 Android Basics D R. M I C H A E L J. R E A L E F A L L

EECS 4443 Mobile User Interfaces. More About Layouts. Scott MacKenzie. York University. Overview (Review)

EMBEDDED SYSTEMS PROGRAMMING Application Tip: Managing Screen Orientation

Produced by. Mobile Application Development. David Drohan Department of Computing & Mathematics Waterford Institute of Technology

Android Basics. Android UI Architecture. Android UI 1

Lab 1 - Setting up the User s Profile UI

Let s take a display of HTC Desire smartphone as an example. Screen size = 3.7 inches, resolution = 800x480 pixels.

Graphical User Interfaces

Android Specifics. Jonathan Diehl (Informatik 10) Hendrik Thüs (Informatik 9)

EECS 4443 Mobile User Interfaces. More About Layouts. Scott MacKenzie. York University

Programming with Android: Introduction. Layouts. Dipartimento di Informatica: Scienza e Ingegneria Università di Bologna

Mobile Application Development Android

Android UI: Overview

Programming in Android. Nick Bopp

Overview. What are layouts Creating and using layouts Common layouts and examples Layout parameters Types of views Event listeners

INTRODUCTION TO ANDROID

CS371m - Mobile Computing. User Interface Basics

10.1 Introduction. Higher Level Processing. Word Recogniton Model. Text Output. Voice Signals. Spoken Words. Syntax, Semantics, Pragmatics

ES E 3 3 L a L b 5 Android development

Mobile User Interfaces

MVC Apps Basic Widget Lifecycle Logging Debugging Dialogs

Our First Android Application

Eventually, you'll be returned to the AVD Manager. From there, you'll see your new device.

Introductory Mobile App Development

Adapter.

User Interface Development. CSE 5236: Mobile Application Development Instructor: Adam C. Champion Course Coordinator: Dr.

Produced by. Mobile Application Development. Higher Diploma in Science in Computer Science. Eamonn de Leastar

Topics of Discussion

Android CardView Tutorial

Android Application Development

Android Apps Development for Mobile and Tablet Device (Level I) Lesson 2

CS 4330/5390: Mobile Application Development Exam 1

Produced by. Mobile Application Development. Eamonn de Leastar

Getting Started. Dr. Miguel A. Labrador Department of Computer Science & Engineering

The Internet. CS 2046 Mobile Application Development Fall Jeff Davidson CS 2046

Diving into Android. By Jeroen Tietema. Jeroen Tietema,

EMBEDDED SYSTEMS PROGRAMMING Application Tip: Saving State

Mobile Computing Practice # 2a Android Applications - Interface

CS260 Intro to Java & Android 05.Android UI(Part I)

Vienos veiklos būsena. Theory

Mobile Programming Lecture 3. Resources, Selection, Activities, Intents

Mobile and Ubiquitous Computing: Android Programming (part 3)

CS 528 Mobile and Ubiquitous Computing Lecture 2a: Introduction to Android Programming. Emmanuel Agu

05. RecyclerView and Styles

<uses-permission android:name="android.permission.internet"/>

Fragment Example Create the following files and test the application on emulator or device.

AND-401 Android Certification. The exam is excluded, but we cover and support you in full if you want to sit for the international exam.

Software Practice 3 Before we start Today s lecture Today s Task Team organization

Android Programming Lecture 2 9/7/2011

Mobile Computing Fragments

Developing Android Applications

Practical 1.ListView example

ANDROID APPS DEVELOPMENT FOR MOBILE GAME

Produced by. Mobile Application Development. Higher Diploma in Science in Computer Science. Eamonn de Leastar

Lab Exercise Git: A distributed version control system

Intents. Your first app assignment

Fragments. Lecture 10

Android App Development

The World of List View. Romain Guy and Adam Powell May 19, 2010

Figure 2.10 demonstrates the creation of a new project named Chapter2 using the wizard.

ANDROID APPS DEVELOPMENT FOR MOBILE AND TABLET DEVICE (LEVEL I)

Programming with Android: Introduction. Layouts. Luca Bedogni. Dipartimento di Informatica: Scienza e Ingegneria Università di Bologna

ConstraintLayouts in Android

User Interface: Layout. Asst. Prof. Dr. Kanda Runapongsa Saikaew Computer Engineering Khon Kaen University

CS260 Intro to Java & Android 05.Android UI(Part I)

MAD ASSIGNMENT NO 2. Submitted by: Rehan Asghar BSSE AUGUST 25, SUBMITTED TO: SIR WAQAS ASGHAR Superior CS&IT Dept.

Fragments were added to the Android API in Honeycomb, API 11. The primary classes related to fragments are: android.app.fragment

Sizing and Positioning

CS 4518 Mobile and Ubiquitous Computing Lecture 2: Introduction to Android Programming. Emmanuel Agu

GUI Design for Android Applications

Applied Cognitive Computing Fall 2016 Android Application + IBM Bluemix (Cloudant NoSQL DB)

Getting Started With Android Feature Flags

Wireless Vehicle Bus Adapter (WVA) Android Library Tutorial

CSE 660 Lab 3 Khoi Pham Thanh Ho April 19 th, 2015

android-espresso #androidespresso

ANDROID USER INTERFACE

Introduction To JAVA Programming Language

Solving an Android Threading Problem

What is version control? (discuss) Who has used version control? Favorite VCS? Uses of version control (read)

ANDROID APPS DEVELOPMENT FOR MOBILE AND TABLET DEVICE (LEVEL I)

Assignment 1: Port & Starboard

MATERIAL DESIGN. Android Elective Course 4th Semester. June 2016 Teacher: Anders Kristian Børjesson. Ovidiu Floca

Understand applications and their components. activity service broadcast receiver content provider intent AndroidManifest.xml

CS 528 Mobile and Ubiquitous Computing Lecture 2a: Android UI Design in XML + Examples. Emmanuel Agu

Chapter 5 Flashing Neon FrameLayout

Transcription:

ETSN05, Fall 2017, Version 1.0 Software Development of Large Systems Lab 2 preparations Read through this document carefully. In order to pass lab 2, you will need to understand the topics presented in this document. You can skip sections that you are familiar with. 1. Versioning with git When programming in groups of people, it s essential to version the code. One of the most popular versioning tools is git. Some benefits of git are: Tracking of all file changes / availability of change history. All versions and associated modifications of a file are preserved. Facilitates code sharing and development in groups. Easy to merge changes to a file performed by multiple individuals. During lab 2 you will version an app which can also serve as a starting point for your project. If you are interested in learning about git, you can read more about it at https://gitscm.com/book/en/v2/. 1.1. Command line vs GUI There are two ways of using git, from the command line and via a GUI, like the one prebuilt into Android Studio. For those that do not have any experience with git, we recommend the command line interface for the following reasons: Many troubleshooting instructions for git that can be found on the internet, are given with the command line interface in mind. Simple way to learn various git commands. GUI interfaces can incorporate several commands within a single button. GUIs sometimes do not implement all the git functionality, and can be buggy. Please note, on Windows, the git command line is called Git Bash. Git and Git Bash are not installed on Windows by default. 1.2. Remote and local repositories In git there are local and remote repositories. When you work on code on your computer and you version it, you are working on your local repository. Every programmer in a group is working on their own local repository. Then, when you want to share your work with the rest of the group, you push to the remote repository. From there, other programmers can pull the

changes when they want, thus resulting in the code you wrote being distributed to the entire group. To avoid problems, only push your changes to the remote if the code you intend to push compiles and runs correctly. 1.3. Staging and committing changes Versioning in git is done via commits. When changes to files are made, they should be committed to the local repository. Each commit consists out of files (note that each change to the code may modify multiple files) that are to be committed, and a commit message describing what has changed. Since changes to multiple files can be committed at the same time, there needs to be a way to specify them before making the commit. This process is called staging. The command to stage a file(or files) is: git add <file_name> [file_names] To find out which files you have staged, and which ones have changed but still haven t been staged, you can type: git status After files have been staged, it s time to commit them: git commit If you do not have any Linux experience, beware that running this command will open vi editor which might not be the most intuitive for a new user. To avoid using vi, you can include the commit message in the command itself: git commit -m Commit message If you happen to enter vi by mistake, you can exit it and abort the commit by typing :q! end pressing enter. You can also change the default git editor to notepad with the following command git config core.editor notepad

Now your changes should be committed. When a new project is started, in theory, there are no preexisting files. In practice, e.g. when developing in Android Studio, some new project files will be generated. As of this point, nothing has been versioned yet, and hence to complete the versioning, the project files need to be staged and committed. Git was designed to version text files, not images or binary files. There are also many files, especially in Android Studio, that are generated automatically throughout the session. Those files shouldn t be committed either. To inform git which files should be ignored, one can create a file named.gitignore and list files that should not be version controlled. In part 1 of lab 2, git was initialized using Android Studio GUI. During that process a.gitignore file was generated automatically, listing many files and directories that shouldn t be committed. It s a good practice to keep the commits small. A rule of thumb is to only commit one logical change at a time. 1.4. Pushing changes to remote In order to share local changes of the code with the other programmers in the group, the changes need to be pushed to the remote repository. Multiple commits can be pushed at the same time git push The first time changed files are pushed to a remote repository, the following command should be used git push -u origin master The origin stands for remote name and master is the branch you are pushing to. 1.5. Pulling changes from remote When other programmers have shared their code, it s often a good idea to integrate these changes into your version of the code as soon as possible. Before you can do that, all your current changes must be committed or stashed (read more about stashing here https://gitscm.com/book/en/v2/git-tools-stashing-and-cleaning ). To pull the changes from the remote use the following command git pull If this process goes smoothly, the changes from the remote will be automatically merged with your local repository. You will be asked to write a merge commit message. Generally, the

commit message Merge commit is enough for merges. If you haven t changed your editor to notepad as described in section 1.3, git will open vi with a default merge commit message already written. To accept it type :wq and press enter. When working in a group, especially on small projects, the pull command can and most likely will cause merge conflicts. How to deal with them is described in the next section. 1.6. Dealing with merge conflicts Merge conflicts can occur when there exist two different versions of the same code. After a pull the prompt will tell you to fix the merge conflicts and then commit the merge. It will also list the files that contain the conflicts. When you open the files, you will see something like this in places where the conflicts occurred: <<<<<<< HEAD:file_name Your version of the code ======= Remote s version of the code >>>>>>> master:file_name Choose one of the versions or write code that includes content from both versions, and remove the merge conflict markers. Remember that one of the versions is the code that you added, and the other is code that someone else added, so simply removing the other programmers work is not an option. After you have fixed all merge conflicts, you can commit to finalize the merge. It s a good practice to test if the code still works after merging, in case you missed a conflict or your merge has cause the code to stop working. 2. Android XML resources In Android, many things are defined in XML resource files. A few advantages with XML resources are They remove code duplication by defining easily accessible resources They are free of implementation details Independent of language the app is programmed in. Can be C++ or C# Android provides convenient ways of translating apps with XML resources Easy to maintain different parallel layouts for different devices and even device orientations Android converts the resources internally so that they can be used in the apps. For example, when an Activity starts, its Views (UI components) are inflated from the XML resources

In Android, all UI components extend a base class called View. They are referred to as views. There are also views that contain(group) other views. They extend a base class called ViewGroup. In this document they are referred to as containers. Note that containers can contain other containers. 2.1. XML syntax XML resources in Android consist out of tags that define the type of object, its properties, and optionally, for some objects, their sub-objects. The syntax is very intuitive. To get an idea how it works, take a look at Appendix 1 that contains the layout resource of the main Activity in lab 2. In the appendix you can see simple tags, like <TextView android:text="@string/some_text" android:textstyle="bold" android:textsize="@dimen/some_text_size" android:layout_marginbottom="@dimen/default_item_margin" android:layout_width="wrap_content" android:layout_height="wrap_content" /> This defines a TextView and defines properties like the dimensions, margins, text size, text style and text of the object. When editing XML resources in Android Studio, make use of the auto-completion features, they help to avoid errors and save a lot of time. When defining dimensions of views in Android, wrap_content and match_parent are often used. As their names suggest, they specify that their view is supposed to either be big enough to properly display its content or span the entire width/height of its container respectively. You might come across fill_parent in older code. It s a deprecated version of match_parent. In the appendix, there are two containers, LinearLayouts that group views together. Notice that they have an end tag, </LinearLayout>. One of them is the root tag that contains everything else in the layout and spans the entire screen, and the other one is there in order to place the Seekbar and the TextView next to each other. Without it, the TextView would appear beneath the Seekbar. Android Studio has a very helpful XML layout editor, that renders the resource as it will appear in the app in real time. You can also use it to add and change things in the layout, however, when you do that, keep in mind to take a look at the XML code from time to time to see if there are no problems that pop out. 2.2. Containers In android there are many different types of containers, however there are a few of them that you will most likely use during the project

LinearLayout- places its views one after another. Can have vertical or horizontal orientation. You can find a good example of this in resource activity_main.xml RelativeLayout- places it views in relation to each other. A good example of it can be found in item_device.xml FrameLayout- does no placement management. All the views added to it are stacked in one place. This can sometimes be useful. When creating layout resources in Android Studio, it likes to make the layouts root a RelativeLayout. If that happens, and you use the graphical XML layout editor, your XML code will likely contain many hardcoded constants, which is a bad practice. It s also easy to make unnoticable mistakes that will make the layout look weird on different devices/device orientations. It s therefore recommended for beginners to use LinearLayouts. 2.3. AndroidManifest Every Android app has a manifest file, called AndroidManifest.xml, which contains general properties of the app, like declaration of its Activities, its permissions, Services, name and so on. This file is rarely modified. 2.4 Obtaining View instances from XML resources Because most of the views that are used in apps are defined in XML resource files, obtaining instances of the classes that represent the views might be confusing for Android beginners. Every Activity and View has a method called findviewbyid. This method takes the view s ID as a parameter and returns a View (that has to be casted to the desired View subclass). For this to work the view has to have an ID property defined in its resource file. The following code will return an instance of a Button with ID list_button Button button = (Button) findviewbyid(r.id.list_button); R is a file that regenerates automatically every time you add a resource to your project. This file contains references to the resources that can be used in Java code. As previously stated, the resource has to have an ID if you want to find it by ID. The following code will add an ID property to your tag android:id="@+id/your_id" Note the plus sign before the id. You have to have it if you are defining a new ID. You should not have it when you use previously defined ID s like in the following case

android:layout_torightof="@id/mac_label" 3. Activities and their lifecycles Activities are the heart of Android. They are what you perceive as the app windows. However, they are not the apps, because one app may contain many Activities. Each activity has to be declared in your app s manifest. Android also finds out which Activity is your starting activity from there. 3.1. Compatibility and the support library One of Android s best features is backwards compatibility. This means that when the Android system updates, the old apps will not stop working. However, apps can still target a specific version of Android and above, in which case they will not work on previous versions of Android. It s beneficial to support lower versions of the system in order to reach as many users as possible. The backwards compatibility introduces an issue. What if you want your app to run on older devices as well as the new ones, but you don t want to have to write code for each specific version of Android that you support? For example, you want to use the colored toolbar introduced in Android 5.0 Material Design, like on the picture below? To solve this problem, the support library has been introduced. Normally, the new features are included in the Android system. Obviously, they can t be accessed from older system versions. The support library adds these features independently of the system, allowing you to run on older Android and use the new features. This has a few consequences however. The most obvious one is that you have to use the AppCompatActivities instead of Android s Activities. The AppCompatActivity does the same things as a normal Activity, but it comes from the support library. To avoid confusion and weird errors, once you have decided to use the support library, stick to it. All new Activites that you add should be AppCompatActivites. From this point forward, whenever

the term Activity is used in this document, it can either mean Android s Activity or support library s AppCompatActivity, depending on what you chose to go with for your app. 3.2. Starting Activites To start Activities in Android, Intents are used. When creating an Intent, one needs to provide the Context(Activity that starts the other Activity), and the class of the Activity to start like so Intent i = new Intent(this, OtherActivity.class); This code should be called from within an Activity so that this is an instance of Activity. However, Intents are often created inside anonymous inner classes that are inside activities, as you will have to do in lab 2. In those cases, this will point to an instance of the anonymous inner class rather than the surrounding Activity. The following syntax solves that problem Intent i = new Intent(MainActivity.this, OtherActivity.class); Where MainActivity is the activity that starts OtherActivity. Intents can also pass values to the new Activity. These are referred to as extras and are put inside the Intent as follows i.putextra("key", "value"); The first argument is the key. This String key is later used to retrieve the right value from the intent. It s a good practice to have the keys as public static constants in the Activity. The second argument is the value to pass. The putextra method has been overloaded for all builtin Java types, so the passed values don t have to be Strings. To retrieve the value in the new Activity do as follows getintent().getstringextra("key"); After the intent has been constructed and loaded with extras, you can start a new Activity like this startactivity(i); 3.3. Activity lifecycles Activity lifecycles allow for ways to execute certain code when the app enters certain states of existence. For example, the oncreate method is called when the Activity is first created. By

overriding this method, custom behavior can be executed when the activity starts. The Android Developers Guide has a very good explanation and description of the lifecycles, and can be found here https://developer.android.com/guide/components/activities/activity-lifecycle.html. Read at least the intro and the first chapter, Activity-lifecycle concepts. 4. Action listeners To define what happens when certain events occur, for example what happens when a user presses a button, you can use action listeners. Because you can t pass functions as parameters in Java, you have to pass classes that implement certain interfaces, that contain the functions that you want to pass as parameters. To make this easier, Java has anonymous inner classes. 4.1. Anonymous inner classes Even though you can, it s inconvenient to create a new file with a new class each time you want to pass a behavior as a parameter. Often these classes are only used once and they would clutter up the workspace pretty quickly. Anonymous inner classes exist for this purpose. They work on a simple principle- they are instances of interfaces (or abstract classes). This is normally forbidden in Java, but it is allowed if you implement the lacking methods on the spot. This concept is easiest to explain with an example. Consider having a button instance named button, that should write to the log when it s pressed. To define what happens when it s pressed, you can call its method setonclicklistener that takes an OnClickListener instance as a parameter, which defines the behavior of the button. You know that you will only use this kind of behavior for this button, and you don t want to create a separate class just for that. Instead you write the following button.setonclicklistener(new View.OnClickListener() { @Override public void onclick(view view) { Log.d("listButton", "The button was pressed"); } }); As you can see, you create a new instance of View.OnClickListener even though it s an interface, and you implement the missing methods on the spot. You can also see that the resulting new class has no name. Hence the anonymous. Android Studio provides an easy way of generating anonymous inner classes, to save time. To get the same code as in the above example, first just create an instance of the listener without overriding any methods button.setonclicklistener(new View.OnClickListener());

Then left click somewhere on error that the Studio marks out, and press Alt + Enter, and then pick the Implement methods alternative, and press Ok in the next dialog. 4.2. How to find them If you are a beginner Android developer you might have troubles knowing what kind of listeners there are. An easy way of getting a list of what kind of listeners there are is to type the name of the variable you wish to define behavior for, then a dot and lastly type listener. Android Studio will show a drop-down menu with methods that have the listener string in them, like shown on the picture below You can then find more information about the certain listener by googling it. It s worth to note that ListView has an onitemclicklistener where you can define what happens when the user presses on one of the items in the list. 5. ListView ListView is one of the most essential views in Android. It s used to present lists of data in an intuitive way. You can define behavior for element clicks, customize how the elements are presented and much more. A more resource friendly alternative to ListView is the RecyclerView. It recycles old views to avoid unnecessary and expensive instantiation and wasting of memory. For the app in this project a simple ListView is sufficient, but for apps like for example 9gag, where each element of the list contains an image and the list is appended with new content infinitely, recycling is a necessity to avoid running out of memory.

5.1. Adapters ListView uses Adapters to represent its elements. Most commonly used implementation of the Adapter interface is the ArrayAdapter that can store the elements that it represents. In this document we will focus on ArrayAdapter. ArrayAdapter behaves like an ArrayList, meaning you can add elements to it using the add and addall methods. You can also remove all its elements with the method clear. To create an adapter, at least three things need to be provided, the context (activity), the type of the objects it will represent and the resource layout which will be used for each item in the list. For example new ArrayAdapter<String>(this, android.r.layout.simple_list_item_1); You can provide any type you want to be represented. By default, the ArrayAdapter will call the object s tostring method. If you re seeing hashes in your list, don t forget to override the tostring method, otherwise Object s implementation is used. Don t forget to set your ListViews adapter with the setadapter method. 5.2. Custom adapters ArrayAdapter is good for proof of concepts and tests, but most of the time, the elements need to be represented by more than just one string. To do that, a custom implementation of Adapter has to be created. Luckily, ArrayAdapter can also be extended saving the programmers some grunt-work. The main method that has to be overridden is the getview method, which is called every time an element has to be presented in the list. Another useful method is getitem, which returns the instance of the element at a certain position. An example implementation of a custom adapter can be found in Appendix 2. 6. AsyncTasks Android, like every other modern operating system supports Threads. Threads are a way to concurrently run multiple things at the same time, or at least make it seem like they do (on single core processors with multiple threads, each thread runs for a short while before giving the processor to the next thread). In Android, all the UI updates run on a so called UI-thread. When

For performing requests over the internet and executing other time-consuming tasks, there is a class called AsyncTask. When started, AsyncTask (hereby referred to as async) runs on a separate thread. Android Developers Guide has a very good introduction to how properly use asyncs. You can find it at https://developer.android.com/reference/android/os/asynctask.html.

Appendix 1: activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_default_padding" android:orientation="vertical" tools:context=".mainactivity"> <TextView android:text="@string/some_text" android:textstyle="bold" android:textsize="@dimen/some_text_size" android:layout_marginbottom="@dimen/default_item_margin" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <SeekBar android:id="@+id/seekbar" android:layout_width="0dp" android:layout_weight="10" android:max="0xff" android:progress="0x0" android:layout_height="wrap_content" /> <TextView android:id="@+id/seek_state" android:layout_width="0dp" android:layout_weight="1" android:text="0" android:gravity="center" android:layout_height="wrap_content" /> </LinearLayout> <EditText

android:layout_margintop="@dimen/default_item_margin" android:hint="@string/editbox_hint" android:layout_marginbottom="@dimen/default_item_margin" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> Appendix 2: Example implementation of custom adapter public class DeviceAdapter extends ArrayAdapter<DeviceBean> { private Context context; public DeviceAdapter(@NonNull Context context) { super(context, R.layout.item_device); this.context = context; } @Override public View getview(int position, View convertview, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context.getsystemservice(context.layout_inflater_service); View view = inflater.inflate(r.layout.item_device, parent, false); TextView name = (TextView) view.findviewbyid(r.id.device_name); TextView mac = (TextView) view.findviewbyid(r.id.device_mac); TextView id = (TextView) view.findviewbyid(r.id.device_id); TextView state = (TextView) view.findviewbyid(r.id.device_state); DeviceBean item = getitem(position); name.settext(item.getname()); mac.settext(item.getdeviceaddress()); id.settext(integer.tostring(item.getid())); boolean statebool = item.getstatus() == 1; state.settext(statebool? R.string.on : R.string.off); state.settextcolor(statebool? Color.GREEN : Color.RED); } } return view;