I wrote simple app on react-native. It consists of <ListView> that shows <Image> in rows. Images are fetched from the network. It runs on iOS very well. But on Android if stucks when image appears. FPS is 0.9-3.2;
I used systrace tool to figure out what is going on. Here is a screenshot of it.
It looks like everything is done on UI thread.
Here is a render function of my class:
render() {
return (
<View style={styles.container}>
<ListView
style={styles.list}
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
</View>
);
}
renderRow(rowData) {
return <Image
style={{ width: 320, height: 320 }}
source={{uri: rowData.coverPhoto}} />
}
I have aa filling that I missed something. Can somebody help me figure out what exactly ?
Thanks!
I ran into the same problem recently and figured out what's causing this and how to solve it (at least for me). I know this is old, but I'll leave this here in case somebody needs it.
The Cause
For me it was the image from the net. Its resolution is huge (more than 3000x4000) while my <Image /> component was styled to be small (50x50 to be exact).
The Solution
There's a prop for <Image /> specifically for Android, which is resizeMethod (this is different from resizeMode). I used resizeMethod: resize and the app runs well on Android. Here's the documentation for more info.
Try change
renderRow={this.renderRow.bind(this)}
to
renderRow={this.renderRow}
Related
Before you link me to another question similar to this one, such as this or that. I will say that I have done exactly what the answers said, but my gif won't animate as it should (It is displayed though).
Here is what I've done in a function, which is displayed through the main App function Stack.Screen within a NavigationContainer and Stack.Navigator. (I'm using React Navigation to move across screens, the context here is that a button is pressed and it displays the contents of the DetailsScreen function)
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 2, alignItems: 'center', justifyContent: 'center' }}>
<Image source={require('./src/gif/moving.gif')} />
<Text>Here is a gif</Text>
</View>
);
}
This displays the first still image of my gif, but doesn't animate it.
I also already went ahead and placed the implementations in the build.gradle dependencies, but it didn't do anything for me. I have a feeling the problem lies there.
implementation 'com.facebook.fresco:fresco:1.+'
// For animated GIF support
implementation 'com.facebook.fresco:animated-gif:1.+'
// For WebP support, including animated WebP
implementation 'com.facebook.fresco:animated-webp:1.+'
implementation 'com.facebook.fresco:webpsupport:1.+'
(I already checked fresco's new implementation version 2, but it still didn't help. I also tried changing from a specific version, still doesn't work)
I am using React Native version 0.67. (I tried starting it again while downgrading react-native to 0.66 and it still doesn't work.)
Also, not sure if this has to do with anything in this screenshot here, this is what I had by default and gave me this error message as soon as I opened the file, but the program launches just fine even with that on
Doing it normally in the main App() function starting first displays the gif, but still remains as a still image.
What should I do? I mean... what else can I do?
Edit:
I found the solution to the problem... it was a simple case of just cold booting the emulator I was using from android studio.
However, Tadej's answer is valid, as the view style aligning messes up the gif a bit. If you are having a similar problem and the answer doesn't help, try cold booting your emulator, or even reinstall a newer one... or alternatively, use a real android phone to test these sorts of things.
Anyway, thanks a lot for the help Tadej ! I hope this question has helped others in my situation.
Tadej Slemenšek
This worked for me. Setting height and width on Image prop did not show the gif. So I flexed it and added maxWidth and maxHeight.
const imageUrl = 'https://media.giphy.com/media/xT0xeCCINrlk96yc0w/giphy.gif';
const App = () => {
const { width } = useWindowDimensions();
return (
<View style={{flex: 1}}>
<Image style={{flex: 1, maxWidth: width, maxHeight: width}} source={{uri: imageUrl}}/>
</View>
);
};
Below is the simple code I have.
change(text) {
this.setState({text});
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome, what is your name?
</Text>
<TextInput
style={{height: 40, width: 200}}
onChangeText={this.change.bind(this)}
value={this.state.text}
/>
</View>
);
}
It works as expected in iOS. In Android, it shows the Text and TextInput field. However anything I type in TextInput does not show up.
I have two questions basically.
First one is, what might be going wrong here?
Second and more important question is, how do I debug a problem like this? I used ReactNative debugger and put a breakpoint in change function, it doesn't get called.
I also checked the generated native code in anticipation to debug using Android Studio. Didn't see anything in the code there where I can possibly put a breakpoint.
If in case it helps someone - here is what I found.
I was running Android emulator with API level 25 (Nougat).
When I switched to API level 23 (Marshmallow) it started working.
i am using the React Native Picker and I am having problems on loading the picker values on Android.
This is my component code:
render() {
return (
<View style={styles.pickerContainer}>
<Picker
style={{width: 100}}
selectedValue={"10"}
mode="dialog">
{this._renderPickItems()}
</Picker>
</View>
)
}
_renderPickItems() {
const PickerItem = Picker.Item
return this.state.minutesList.map((value) => (
<PickerItem label={`${value} min`} value={value} key={`minutes_${value}`} />
))
}
When I run my app on Android, the elements of the Picker are not being shown on the screen for some reason (minutesList is an Array of numbers), in the other hand if I ran the same code on iOS, the items are being shown correctly.
Another thing is if I add Picker.Item directly into the Picker (like the Picker doc example) it works like expected, but i do not want to add 99 lines for each element.
Why the function returing the Picker.Items works on iOS and not Android? Maybe there is something basic missing and I do not know what it is.
Some images on the problem:
iOS works like expected
Thanks for the help.
this issue is older, but i'll aswner to help someone that have this same problem and see this question.
I my case, inside the function _renderPickItems() i created a array and for each Picker.Item i create, i put inside of array and the last i returned array.
Works fine to me.
Hello I'm just a newbie on react native.
I'm trying to use a Facebook tutorial for the image component
export default class PropertyFinder extends Component {
render() {
let pic = {
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
};
var yourPicture = require ('./images/image1.jpg');
return (
<ScrollView>
<Image source={{uri: 'http://i.imgur.com/UePbdph.jpg'}} style={{width: 200, height: 227}} />
<Text> test </Text>
<Image source={pic} style={{width: 193, height: 110}}/>
<Image source={yourPicture}/>
<View>
<Image source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}} style={{width: 400, height: 400}} />
</View>
</ScrollView>
);
}
}
I ran this on the AVD emulator and it works all the images show
But, I tried to debug on the device (old lenovo API 16) and an image is shown only for the local image var yourPicture , all the URI http / https images aren't showing. They are just blank.
So I'm curious, how can this be happening?
I've tried to search the forum, but can't found any solution. I also tried to release the apk, and install it on my old lenovo, but I still get the same result. (only local image shows)
Finally I tried to install it on my new xiaomi (android 6), and all the images show..
Hmm this behavior is odd, because React native supports android 16, right?
minSdkVersion 16
Any way to fix this?
Thank you very much......
Are you using big images?
You should try to use android:largeheap="true" to see if it's works with that. If the image appear than mean you have a memory issue on old devices.
android:largeheap="true" is not a solution. It should be only used for apps which require a lot of memory (like drawing on picture).
You can use ImageOptim to reduce the size of your files
Does anyone know how to implement a listview refresher for android in React-Native?
I think this is a common problem a lot of people have.
There is react-native-refreshable-listview , but it does not support android.
You should be able to accomplish this behavior by using the PullToRefreshViewAndroid (https://facebook.github.io/react-native/docs/pulltorefreshviewandroid.html#content) launched with React Native 0.16.
As mentioned in this issue: https://github.com/facebook/react-native/issues/4793, you might have to use style={{flex: 1}} on the PullToRefreshView to achieve the result you want, something like this:
<PullToRefreshViewAndroid
refreshing={isRefreshing}
onRefresh={this.onRefresh}
style={{ flex: 1 }}>
<ListView
...listViewProps />
</PullToRefreshViewAndroid>
Then you should get the same behaviour as ReactNativeRefreshableListView gives you, but on Android.
React-native has an out of the box solution for pull to refresh
<ListView
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this.onRefresh.bind(this)}
/>
}
...
dataSource={this.state.dataSource}
/>
and elsewhere in your class, an onRefresh() function...
onRefresh() {
this.setState({refreshing:true});
//refresh data and set refreshing to false as appropriate for your app...
}