Dynamic View creation performance issue - android

I need to create dynamic layout (i.e. without using xml at all ). On the mobile device an service api will provide jsons. These jsons will hold the layout pattern or design to draw dynamically.
These layout jsons will coresspond to different templates that we need to show. It can be more than 150 templates.
Please find below a sample template :-
Template.json
{
"data": {
"layouts": [
{
"layoutId": 0,
"width": "34%",
"selectedbackgroundcolor": "#96F2CD",
"gradient": true,
"backgroundcolor": "#afeeb9",
"gradientcolors": [
"#afeeb9",
"#f3f6f7"
],
"strokewidth": 1,
"strokecolor": "#7bad51",
"children": [
{
"children": [
{
"backgroundcolor": "#3074c6",
"type": "label",
"field": "textfield1",
"fontsize": 14,
"textcolor": "#FFFFFF",
"alignment": "right",
"width": 242,
"singleline": true,
"topmargin": 10,
"rightmargin": 10,
"rightpadding": 10,
"bottompadding": 5,
"toppadding": 5
},
{
"backgroundcolor": "#3074c6",
"type": "label",
"text": "textfield: #",
"dependonfield": "textfield1",
"fontsize": 14,
"topmargin": 10,
"textcolor": "#FFFFFF",
"alignment": "right",
"width": 95,
"singleline": true,
"leftpadding": 10,
"bottompadding": 5,
"toppadding": 5,
"leftmargin": 10
}
]
},
{
"children": [
{
"type": "label",
"field": "FormattedClosedDate",
"fontsize": 14,
"textcolor": "#000000",
"alignment": "right",
"width": 90,
"topmargin": 5,
"singleline": true,
"rightmargin": 10
},
{
"type": "label",
"text": "Closed On: ",
"dependonfield": "FormattedClosedDate",
"fontsize": 14,
"topmargin": 5,
"textcolor": "#000000",
"alignment": "right",
"width": 100,
"singleline": true,
"leftmargin": 5,
"bold": true
}
]
},
{
"children": [
{
"type": "label",
"field": "Title",
"textcolor": "#000000",
"alignment": "left",
"fontsize": 17,
"bold": true,
"singleline": true,
"topmargin": 10,
"leftmargin": 10,
"rightmargin": 10
}
]
},
{
"children": [
{
"type": "label",
"field": "Summary",
"textcolor": "#7E957B",
"alignment": "left",
"fontsize": 14,
"leftmargin": 10,
"bottompadding": 20,
"maxline": 2,
"rightmargin": 10
}
]
}
]
}
]
},
"rcode": 100,
"msg": "Success"
}
I wrote the layout parser for these templates. I choose Listview to dynamically inflate the view that was returned from layout parse. Each listview's row is now holding different layout view or template.
So I cannot use the view holder pattern to reuse the view's elements. As views are created dynamically so the view id's are created dynamically.
I am showing 15 items in a list at single point of time. I am using this library to load n items form total x items at aingle point in time---https://github.com/chrisbanes/Android-PullToRefresh.
Now the problems are :-
Memory leak because we are not using the view holder pattern.
Context is used to create new views they are coupled from activities
life cycle.
Views are not destroyed until activity is not destroyed.
Please provide me with an alternate solution of using other than Listview or modify the current approach.

The most important thing for you is be sure to implement Adapter.getItemViewType. Each layout should have its own type identifier. Your convertView parameter, if set, will then always have the correct layout already inflated.
Now you can use the holder pattern again, by using a different holder for each layout.
Edit: I don't think your situation is well suited to ListView. ListView is meant for generally large lists of similar content. Have you considered a vertically oriented LinearLayout within a ScrollView instead?
If your layouts are all different, you have to decide between dynamically generating them in an Adapter (the ListView approach you're already using) which will be slow, or generating them all at once, which might take more memory.
As for your specific concerns:
* Not using Holder pattern does not introduce a memory leak. You might be misunderstanding the purpose of Holder pattern. It's only intended to reduce re-inflation of similar layouts.
* Even with views created from within an Adapter, they're still created with your activity's context. They are UI elements, so will always be bound to the Activity lifecycle.

Related

Find focusable accessibility nodes in AccessibilityService' AccessibilityEvent

I want to extract the views that will get accessibility focus when touch exploration mode of TalkBack would have been used. I want to base this on an AccessibilityEvent. AccessibilityNodeInfo does have the necessary fields, but they do not seem to reflect the correct values.
The screenshot shows 10 views that TalkBack focusses on and pronounces. Each element that gets focus, gets a rectangle drawn on top. I mapped these nodes to JSON for this question.
Each node has multiple potential fields that could tell me which view gets focus and which view does not. isImportantForAccessibility and actionList are contenders, but there's not a 1 to 1 relationship with the screenshot and the nodes. Also, TalkBack receives an event containing the selected node, so it seems that source code cannot be used to reverse engineer the logic.
Which fields can tell me TalkBack will focus on that node and pronounce the content?
3 examples that show my investigation, but are not per se needed to understand my question:
For Files isVisibleToUser and isImportantForAccessibility are true, so it makes sense to focus and pronounce.
{
"actionList": [
"ACTION_SELECT",
"ACTION_CLEAR_SELECTION",
"ACTION_ACCESSIBILITY_FOCUS",
"ACTION_NEXT_AT_MOVEMENT_GRANULARITY",
"ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY",
"ACTION_SET_SELECTION",
"ACTION_SHOW_ON_SCREEN"
],
"boundsInScreen": "44,105,183,193",
"className": "android.widget.TextView",
"collectionInfo": null,
"collectionItemInfo": null,
"contentDescription": null,
"isAccessibilityFocused": false,
"isFocusable": false,
"isFocused": false,
"isHeading": false,
"isImportantForAccessibility": true,
"isVisibleToUser": true,
"sourceNodeId": -4294955806,
"text": "Files",
"traverseAfterId": null,
"traverseBeforeId": null,
"children": []
}
For Recent, there's an LinearLayout with a nested TextView. isVisibleToUser and isImportantForAccessibility are true for both. The LinearLayout does not have a contentDescription and on its own it's not interesting for accessibility but it does get focus. The TextView is interesting, but does not get focus.
{
"actionList": [
"ACTION_SELECT",
"ACTION_CLEAR_SELECTION",
"ACTION_CLICK",
"ACTION_ACCESSIBILITY_FOCUS",
"ACTION_SHOW_ON_SCREEN"
],
"boundsInScreen": "0,237,770,391",
"className": "android.widget.LinearLayout",
"collectionInfo": null,
"collectionItemInfo": {
"columnIndex": 0,
"columnSpan": 1,
"isSelected": false,
"rowIndex": 0,
"rowSpan": 1
},
"contentDescription": null,
"isAccessibilityFocused": false,
"isFocusable": false,
"isFocused": false,
"isHeading": false,
"isImportantForAccessibility": true,
"isVisibleToUser": true,
"sourceNodeId": -4294954792,
"text": null,
"traverseAfterId": null,
"traverseBeforeId": null,
"children": [{
"actionList": [
"ACTION_SELECT",
"ACTION_CLEAR_SELECTION",
"ACTION_ACCESSIBILITY_FOCUS",
"ACTION_NEXT_AT_MOVEMENT_GRANULARITY",
"ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY",
"ACTION_SET_SELECTION",
"ACTION_SHOW_ON_SCREEN"
],
"boundsInScreen": "176,287,748,340",
"className": "android.widget.TextView",
"collectionInfo": null,
"collectionItemInfo": null,
"contentDescription": null,
"isAccessibilityFocused": false,
"isFocusable": false,
"isFocused": false,
"isHeading": false,
"isImportantForAccessibility": true,
"isVisibleToUser": true,
"sourceNodeId": -4294954788,
"text": "Recent",
"traverseAfterId": null,
"traverseBeforeId": null,
"children": []
}]
}
Also the divider below Downloads is part of the tree and has isImportantForAccessibility set to true, and can be selected. There is no need to focus on this, TalkBack doesn't focus on it, but the node seem to say it should be.
{
"actionList": [
"ACTION_SELECT",
"ACTION_CLEAR_SELECTION",
"ACTION_ACCESSIBILITY_FOCUS",
"ACTION_SHOW_ON_SCREEN"
],
"boundsInScreen": "0,1161,770,1230",
"className": "android.widget.FrameLayout",
"collectionInfo": null,
"collectionItemInfo": {
"columnIndex": 0,
"columnSpan": 1,
"isSelected": false,
"rowIndex": 6,
"rowSpan": 1
},
"contentDescription": null,
"isAccessibilityFocused": false,
"isFocusable": false,
"isFocused": false,
"isHeading": false,
"isImportantForAccessibility": true,
"isVisibleToUser": true,
"sourceNodeId": -4294954732,
"text": null,
"traverseAfterId": null,
"traverseBeforeId": null,
"children": []
}
For completeness, the xml used of the AccessibilityService:
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackVisual"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true" />
I used an emulator with API 31 to get the tree.

Is there a way to use json format emoticon on android?

I want to receive emoticon from emoji-datasource site as json file and show it in android. How do you do it? The file in json format is:
[
{
"name": "HASH KEY",
"unified": "0023-FE0F-20E3",
"non_qualified": "0023-20E3",
"docomo": "E6E0",
"au": "EB84",
"softbank": "E210",
"google": "FE82C",
"image": "0023-fe0f-20e3.png",
"sheet_x": 0,
"sheet_y": 0,
"short_name": "hash",
"short_names": [
"hash"
],
"text": null,
"texts": null,
"category": "Symbols",
"sort_order": 132,
"added_in": "0.0",
"has_img_apple": true,
"has_img_google": true,
"has_img_twitter": true,
"has_img_facebook": false
},
{
"name": null,
"unified": "002A-FE0F-20E3",
"non_qualified": "002A-20E3",
"docomo": null,
"au": null,
"softbank": null,
"google": null,
"image": "002a-fe0f-20e3.png",
"sheet_x": 0,
"sheet_y": 1,
"short_name": "keycap_star",
"short_names": [
"keycap_star"
],
"text": null,
"texts": null,
"category": "Symbols",
"sort_order": 133,
"added_in": "0.0",
"has_img_apple": true,
"has_img_google": true,
"has_img_twitter": true,
"has_img_facebook": false
},
...
]
Link is here : https://www.npmjs.com/package/emoji-datasource.
I tried the following but it didn't work.
textView.text = String(Character.toChars(0x002AFE0F20E3))
I want to show the user all the emoticons available on the Android device.
Oh, I solved it. Just use in json file google name code.
I dont know that this would serve as a solution but I did something different and wanna share it here so everyone knows.
Content that I create from Android app gets encoded using this. When fetching from server, I decode this using the same method. Content includes emojis as well and they appear perfectly in all devices without knowing the names of the emojis.

Retrieve List of Layout/View's attributes

I'm working on a small learning-tool project that has several different views displayed in various fragments. What I'd like to do is when the user selects a layout or view (e.g. TextView), a dialog pops up that shows all its available attributes (e.g. android:layout_width, android:layout_height, android:focusable, etc). Rather than going through each layout/view and manually typing the attributes in a file or class, I was hoping there was a way to programmatically get the attributes. Currently, I just have a JSON file I'm reading from, but it's becoming extremely tedious. An issue also arises with different API versions.
Just to get an idea of what I'm currently dealing with, here's my JSON file:
{
"LayoutParams": [
"android:layout_height",
"android:layout_width"
],
"MarginLayoutParams": [
"android:layout_margin",
"android:layout_marginBottom",
"android:layout_marginEnd",
"android:layout_marginHorizontal",
"android:layout_marginLeft",
"android:layout_marginRight",
"android:layout_marginStart",
"android:layout_marginTop",
"android:layout_marginVertical"
],
"RelativeLayout": {
"inherited_properties": [
"MarginLayoutParams",
"LayoutParams"
],
"primary_properties": [{
"android:gravity": ["bottom", "center", "center_horizontal", "center_vertical", "clip_horizontal", "clip_vertical", "end", "fill", "fill_horizontal", "fill_vertical", "left", "right", "start", "top"],
"android:ignoreGravity": [""],
"android:layout_above": [],
"android:layout_alignBaseline": [],
"android:layout_alignBottom ": [],
"android:layout_alignEnd": [],
"android:layout_alignLeft": [],
"android:layout_alignParentBottom": [],
"android:layout_alignParentEnd": [],
"android:layout_alignParentLeft": [],
"android:layout_alignParentRight": [],
"android:layout_alignParentStart": [],
"android:layout_alignParentTop": [],
"android:layout_alignRight": [],
"android:layout_alignStart": [],
"android:layout_alignTop": [],
"android:layout_alignWithParentIfMissing": [],
"android:layout_below": [],
"android:layout_centerHorizontal": [],
"android:layout_centerInParent": [],
"android:layout_centerVertical": [],
"android:layout_toEndOf": [],
"android:layout_toLeftOf": [],
"android:layout_toRightOf": [],
"android:layout_toStartOf": []
}]
}
}
You can extract them from R.stylable.
AFAIK, there's no XML schema or DTD defined, so R.stylable might be your only choice.

Parse Nested JSON data in Android

I am trying to parse JSON data which looks like this in android;
{
"data": [{
"http_code": 200,
"message": "success",
"created_at": "2016/10/12",
"categories": [{
"cat_id": 1,
"cat_name": "Business and Commerce",
"subcategories":[{
"subcat_id": 1,
"subcat_name": "Intellectual Property",
"articles":[{
"article_id": 1,
"article_heading": "What is intellectual?",
"article_url": "http://example.com/1"
},{
"article_id": 2,
"article_heading": "Types of intellectual Properties",
"article_url": "http://example.com/2"
}]
}, {
"subcat_id": 2,
"subcat_name": "Business Licensing",
"articles":[{
"article_id": 1,
"article_heading": "What is a license?",
"article_url": "http://example.com/1"
},{
"article_id": 2,
"article_heading": "Types of Business Licenses",
"article_url": "http://example.com/2"
}]
}]
}, {
"cat_id": 2,
"cat_name": "Family Law",
"subcategories":[{
"subcat_id": 3,
"subcat_name": "Domestic Violence",
"articles":[{
"article_id": 1,
"article_heading": "What is domestic violene?",
"article_url": "http://example.com/1"
},{
"article_id": 2,
"article_heading": "Types of domestic violence",
"article_url": "http://example.com/2"
}]
}, {
"subcat_id": 4,
"subcat_name": "Marriage",
"articles":[{
"article_id": 1,
"article_heading": "What is a marriage?",
"article_url": "http://example.com/1"
},{
"article_id": 2,
"article_heading": "Types of marriages",
"article_url": "http://example.com/2"
}]
}]
}]
}]
}
I am supposed to see data for a specific node when I select it via a listview list item click and so on....
So far I have managed to parse all the categories and display them in a listview, but I want to display subcategories for a category I select on the listview.
Set an onItemClickListener on your listview and use the position of the selected item to return the relevant subcategories?
For example, perhaps something along the lines of:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Switch(position) {
case 0:
//get first subcategories array values
break;
case 1:
//get second subcategories array values
break;
....
}
}
Use ExpandableListView, example given on this link.
For json parsing use Google gson, it will make your work easy and efficient.
It seems similar to How to parse this nested JSON array in android
But you can use this lib https://github.com/FasterXML/jackson
to make the work easy and faster using Objects.
It is a small tutorial: JacksonInFiveMinutes
Specially: Full Data Binding (POJO) Example. And JacksonDataBinding
Thanks everyone for your help. I finally managed to solve the issue;
Here is how I did it;
JSONObject jsonObj = new JSONObject(jsonStr);
JSONObject subcategories = jsonObj.getJSONObject("data").getJSONArray("categories").getJSONObject((int)getItemId(position));
Log.e("TAG","Subcategories: " + subcategories);
I don't know if that is the correct way, but it worked in my case.

Android: Bing image search result customization

I am implementing the Bing search for image searching.
I refered this link, and change my response to JSON.
It works and the result is like:
{
"d": {
"results": [{
"__metadata": {
"uri": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Image?Query=\u0027Pepsi\u0027&$skip=0&$top=1",
"type": "ImageResult"
},
"ID": "64737694-fc53-4d68-933d-10edc214fd3a",
"Title": "Pepsi: Like Madonna, its look has been reinvented time and time again ...",
"MediaUrl": "http://tjthesportsgeek.files.wordpress.com/2012/02/pepsi.png",
"SourceUrl": "http://tjthesportsgeek.com/2012/02/14/tale-of-the-tape-coke-vs-pepsi/",
"DisplayUrl": "tjthesportsgeek.com/2012/02/14/tale-of-the-tape-coke-vs-pepsi",
"Width": "1588",
"Height": "2064",
"FileSize": "569827",
"ContentType": "image/png",
"Thumbnail": {
"__metadata": {
"type": "Bing.Thumbnail"
},
"MediaUrl": "http://ts2.mm.bing.net/th?id=OIP.M7f9b9a39639b9ca8bb6f1cba6e35d041H0&pid=15.1",
"ContentType": "image/jpg",
"Width": "369",
"Height": "480",
"FileSize": "19879"
}
},
// Next array element
]
}
}
but what i need is:
The json result with only MediaUrl and MediaUrl of Thumbnail. (As it is possible in Google Custom Search with the help of tag "field" like fields=items(link,image/thumbnailLink))
The image only with medium size. (I searched for this and applied the filter but of no use.)
Please reply with your valuable suggestions.
You can't filter output fields.
Use the parameter: ImageFilters = Size.Medium
My ref: https://onedrive.live.com/view.aspx?resid=9C9479871FBFA822!109&app=Word&authkey=!ACvyZ_MNtngQyCU

Categories

Resources