5th section Refresh and stop refresh List
Despite our assumptions, ignoring a lot of video files that do not need attention, but there are still a lot of things on the device that satisfy our assumptions, we need a "cancel Refresh" function.
If the video has not been refreshed, it is canceled, and then you want to continue the refresh, then you need to manually start the "Refresh" function.
Therefore, prepare a menu item in the upper-right corner of the Actionbar to allow the user to "refresh" or "Stop the Refresh".
5.1 Adding Refresh Menu items
In the documentation for the calculator, we've covered how to add a actionbar menu item, and how to respond to the click of a dish item,
Defines a menu item to a res\xml\menu.xml
file, the app:showAsAction
property walways
is set to,
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_refresh" app:showAsAction="always" android:title="@string/refresh"/></menu>
5.2 The ability to "refresh" and "Stop Refresh"
In the onCreateOptionsMenu()
function, using the defined menu, get the menu item "Refresh" function, according to the current VideoUpdateTask
state, to determine the name of the menu to be displayed,
PrivateMenuItem Mrefreshmenuitem;@Override Public Boolean Oncreateoptionsmenu(Menu menu) {Getmenuinflater (). Inflate (R.menu.menu, menu);//Get "Refresh" menu itemMrefreshmenuitem = Menu.finditem (R.id.menu_refresh);//When Videoupdatetask is in a running state, the title of the menu item displays "Stop Refresh", if((Mvideoupdatetask! =NULL) && (mvideoupdatetask.getstatus () = = AsyncTask.Status.RUNNING)) {Mrefreshmenuitem.settitle (r.string.in_re Fresh); }//When Videoupdatetask is not in a running state, the title of the menu item displays "Refresh", Else{Mrefreshmenuitem.settitle (R.string.refresh); }return true;}
In onOptionsItemSelected()
, depending on VideoUpdateTask
the current state, to determine how to respond to the user's click action,
@Override Public Boolean onoptionsitemselected(MenuItem Item) {Switch(Item.getitemid ()) { CaseR.id.menu_refresh: {if((Mvideoupdatetask! =NULL) && (mvideoupdatetask.getstatus () = = AsyncTask.Status.RUNNING)) {//Cancel Videoupdatetask work when Videoupdatetask is in a running stateMvideoupdatetask.cancel (true); Mvideoupdatetask =NULL; }Else{//When Videoupdatetask is not in a running state, start videoupdatetask workMvideoupdatetask =NewVideoupdatetask (); Mvideoupdatetask.execute ();//Modify the menu item title to "Stop Refresh" if(Mrefreshmenuitem! =NULL) {mrefreshmenuitem.settitle (R.string.in_refresh); } } } Break;default:return Super. oncontextitemselected (item); }return true;}
After Videoupdatetask
has been successfully canceled, its oncancelled ()
function is called; in Videoupdatetask
After the work is done, its onpostexecute ()
function is called, which runs in the main thread, so you can modify the interface here,
@OverrideprotectedvoidonPostExecute(Void result) { updateResult()}@OverrideprotectedvoidonCancelled() { updateResult();}privatevoidupdateResult(){ //修改菜单项的标题为“停止刷新” ifnull) { mRefreshMenuItem.setTitle(R.string.refresh); }}
5.3 Refresh Legacy Issues 5.3.1 Issue 1
When the app starts, it VideoUpdateTask
starts updating the video message, and the user taps "Pause refresh", the task stops, and the user clicks Refresh. We will find that the previously listed videos are listed again.
Originally, when the refresh, did not show the video and not show the video area, has been added and added again.
The solution is to add the video information to the list of data before the first check whether the video has been added, if added, it will not be added.
Rewrite VideoItem
The comparison method, let the comparison of the two VideoItem
principles into: As long as the file is located in the same path, it is considered that the two comparisons refer to the same,
@Overridepublicbooleanequals(Object o) { VideoItem another = (VideoItem) o; return another.path.equals(this.path);}
In VideoUpdateTask
the doInBackground()
function, add the video information to ListView
the data set- mVideoItemList
before the first to determine whether it contains the video, if not included, sent to the main thread update interface; Compare the video is the same basis, is the previously overridden equals()
function,
@OverrideprotecteddoInBackground(Object... params) { ...... ifnull) { while(cursor.moveToNext()) { ...... new VideoItem(path, name, createdTime); //判断出之前没有这个视频,才发送给主线程更新界面 iffalse) { publishProgress(item); } } cursor.close(); } returnnull;}
5.3.2 Question 2
The solution to question 1 introduces another question: If the video is duplicated, then it is not possible to ignore it when creating a video thumbnail, because creating a video thumbnail is a very memory and time consuming thing.
So we're going to change the strategy for creating thumbnails, and don't let it start, but let's decide whether to create thumbnails based on conditions.
Modify VideoItem
the design into,
Videoitem (String strpath, String strName, String createdtime) { This. Path = strpath; This. name = StrName; SimpleDateFormat SF =NewSimpleDateFormat ("yy mm month DD day hh mm"); Date d =NewDate (long.valueof (createdtime) * +); This. Createdtime = Sf.format (d);;}//The ability to create thumbnails independentlyvoidCreatethumb () {if( This. Thumb = =NULL) { This. Thumb = Thumbnailutils.createvideothumbnail ( This. path, MediaStore.Images.Thumbnails.MINI_KIND); }}//With Createthumb (), a way to release bitmap resources is requiredvoidReleasethumb () {if( This. Thumb! =NULL){ This. Thumb.recycle (); This. Thumb =NULL; }}
In VideoUpdateTask
the doInBackground()
function,
@OverrideprotecteddoInBackground(Object... params) { ...... ifnull) { while(cursor.moveToNext()) { ...... new VideoItem(path, name, createdTime); iffalse) { //判断需要添加,才创建缩略图 item.createThumb(); publishProgress(item); } } cursor.close(); } returnnull;}
5.3.3 Question 3
If the user pauses the refresh, the video on the device is deleted for another reason, even if the solution with the problem 1 will not be effective, because the ListView
number of video messages saved is more than the actual refresh, not the ListView
redundant data to clear out.
So, to ListView
erase all the extra video, only after the video query is complete, and these real video information has to be saved, in the final comparison will be used.
Save a copy of the video message that really exists,
List<videoitem> mdatalist =NewArraylist<videoitem> ();@OverrideprotectedVoidDoinbackground(Object ... params) { ......if(Cursor! =NULL) { while(Cursor.movetonext ()) { ...... Videoitem item =NewVideoitem (path, name, Createdtime);if(mvideolist.contains (data) = =false) {data.createthumb (); Publishprogress (item); }//Save upMdatalist.add (data); } cursor.close (); }return NULL;}
VideoUpdateTask
After the work is finished (either canceled or completed successfully), it is called onCancelled()
onPostExecute()
, so you can updateResult()
erase the ListView
extra video information in their common invocation,
private void updateresult () {... for (int i = 0 ; i < mvideolist.size (); i++) {if (!mdatalist.contains (Mvideolist.get (i)) {//releases the memory resource occupied by the thumbnail mvideolist.get (i). Releasethumb (); //remove extraneous video information from the data set of the ListView Mvideolist.remove (i); //because a video item is removed, the sequence number of the next video item is reduced by a 1 i--; }} mdatalist.clear (); //notify ' ListView ' data changes, need to refresh Videoitemadapter adapter = (videoitemadapter) mvideolistview.getadapter (); Adapter.notifydatasetchanged ();}
At this point, the video refresh function is complete.
6th section of the video list of the horizontal screen
The device will automatically adjust the layout of the application when it is placed horizontally or vertically, and display the horizontal screen or vertical screen. So is our list of videos.
We can deal with the problem of device rotation in two ways,
The activity does not rotate with the rotation of the device direction, it only has a vertical screen (or only horizontal screen) interface. It's easy to do this by AndroidManifest.xml
adding android:screenOrientation="portrait"
(Keep the vertical screen) to the activity component in the file.
or android:screenOrientation="landscape"
(keep the horizontal screen) of the properties can be;
<manifest xmlns:android="Http://schemas.android.com/apk/res/android" package ="Com.anddle.anddleplayer"> <application ... > <activityandroid:name=". Videolistactivity "android:screenorientation=" Landscape "> </activity>......</Application></manifest>
Rotate the activity to follow the rotation of the device's direction.
We are ready to take the second approach.
6.1 Activity Cycle Switching
The life cycle of the activity also changes when the screen orientation changes.
Created from an activity, to the display, and then to the user's active exit to destroy the activity, it will experience:
onCreate()
-
onStart()
-
onResume()
-
User can interact with activity
onPause()
-
onStop()
-
onDestroy()
;
If an activity is created from, to displayed, and then rotated, then it will go through:
onCreate()
-
onStart()
-
onResume()
-
The user can interact with the activity, where the screen rotates, from the vertical screen to the horizontal screen.
onSaveInstanceState()
-
onPause()
-
onStop()
-
onDestroy()
-
onCreate()
-
onStart()
-
onRestoreInstanceState()
-
onResume()
-
Users can interact with the activity;
You can see that the onCreate()
function is called again when it is rotated. Here, if you have a horizontal layout file, the layout of the onCreate()
setContentView()
horizontal screen will be used, and if not, the default layout file is still used.
6.2 Problems with screen rotation
If the video list changes from a vertical screen to a horizontal screen, then the process of creating it is performed first onDestroy()
onCreate()
. As we'll see in the interface, a list of all the video information has been shown, and after the rotation, it's time to start querying again.
This is obviously not necessary. So we need to make a little change to the video list interface so that it doesn't have to be completely refreshed every time it spins.
In the AndroidManifest.xml
file, add the properties of the activity component to android:screenOrientation="orientation|screenSize"
it;
<manifest xmlns:android="Http://schemas.android.com/apk/res/android" package ="Com.anddle.anddleplayer"> <application ... > <activityandroid:name=". Videolistactivity "android:configchanges=" Orientation|screensize "> </activity>......</Application></manifest>
This activity from creation, to display, then rotation, then it will go through:
onCreate()
-
onStart()
-
onResume()
-
The user can interact with the activity, where the screen rotates, from the vertical screen to the horizontal screen.
onConfigurationChanged()
;
As a result, the activity does not go through the process of destroying, creating, but only after rotating onConfigurationChanged()
. In this case, if there is a horizontal screen layout file for it, then this layout will not be used, because it is onCreate()
not called.
Teach you to do video player (iv)