I have a Flutter app with two tabs,
when I open the first tap, the app gets data from API,
when I move to the second app and return to the first tab, the app connects to the API one more time to get the data,
what is the easier method to save the data from the first time??
use AutomaticKeepAliveClientMixin in the first tab :
class _FirstTabState extends State<FirstTab> with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
super.build(context);
return Container();
}
#override
bool get wantKeepAlive => true;
}
Related
I am working on investment tracking app that will be free for everyone. I am using net Core with blazor and Blazorise for charts.
I stumbled upon a problem with rendering the charts. From the official Blazorise documentation I added method protected override async Task OnAfterRenderAsync(bool firstRender) (see in the code below). This method should redraw the charts the first time the page renders. The problem is that this method always fires twice. It renders the charts in the first go and the second time it leaves them empty (as firstRender = false the second time it fires). If I remove the if block the charts render ok.
Furthermore I've added button that should refresh the data + charts. After pressing this button the charts refresh twice (this is unwanted behaviour as it distracts the users) and what is interesting the data itself (the values) change after the second go.
Have anybody dealt with this problem before?
My html code
...
<div class="btn" #onclick="(async () => await RerenderPage())">Refresh Data</div>
...
My code
List<Models.VM.OverView> overview = new List<Models.VM.OverView>();
protected override async Task OnInitializedAsync()
{
overview = await GetOverview(); //gets overview from api
}
public async Task<List<Models.VM.OverView>> GetOverview()
{
return await Http.GetFromJsonAsync<List<Models.VM.OverView>>("/api/Overview/GetOverView/" + await GetUserIdAsync);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await HandleRedraw();
}
}
async Task HandleRedraw()
{
await pieChart.Clear();
//this method goes in the overview object and gets data from it
await pieChart.AddLabelsDatasetsAndUpdate(GetLabelsPieChart(), GetPieChartDataset());
}
What is the await Rerenderpage() doing ?
From the samples it looks like it employs the user of a bool isAlreadyInitialised flag.
protected override async Task OnAfterRenderAsync( bool firstRender )
{
if ( !isAlreadyInitialised )
{
isAlreadyInitialised = true;
await HandleRedraw();
}
}
I am assuming that async () => await RerenderPage()) calls something that then calls the chart.Update in order for the component to know its statuschanged ?
I just want to be able to display a list of contacts (without even communicating to a server) just the way it is displayed on the "Contacts" native app on the phone.
I have like 1500 contacts and when I try to load the recycler view, all items at once, it lags a lot 2 - 3 seconds.
I've achieved loading more items but with a loading bar and thats not what I want.
I've already tried Threads, Executors, postOnUIThread(), handler.post() and even AsyncTask -> Override -> doOnBackground. Nothing works.
private class CustomTask extends AsyncTask<Void, Void, Void> {
int inserted;
#Override
protected Void doInBackground(Void... param) {
//Do some work
try {
lcf.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
((BaseActivity) lcf.getActivity()).showProgressDialog();
}
});
int currentSize = contactsLoaded.size();
for (inserted = 0; inserted < lcf.getController().getContacts().size() && contactsLoaded.size() < lcf.getController().getContacts().size(); inserted++) {
contactsLoaded.add(lcf.getController().getContacts().get(currentSize + inserted));
notifyItemRangeInserted(contactsLoaded.size() - 1, inserted);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void param) {
//Print Toast or open dialog
//notifyItemRangeInserted(contactsLoaded.size() - 1, 0);
if(!lcf.getController().isSelectedAffiliated()){
lcf.disclaimerLayout.setVisibility(View.VISIBLE);
}else{
lcf.disclaimerLayout.setVisibility(View.GONE);
}
lcf.isLoading=false;
((BaseActivity) lcf.getActivity()).hideProgressDialog();
}
}
That code lives within my adapter, "lcf" is a reference to the fragment. If I use the already loaded list saved on the controller (that I get from the fragment reference) and then just call notifyDataSetChanged() it LAGS like hell. So with this CustomTask I tried to load every item and notify it one by one to a Background task hoping it would make the items pop up quickly and sequentially without interfereing with the UI thread to not freeze the screen. It doesn't work. I am out of options now. I've tried everything.
I would like to implement near real-time OCR on the camera feed of my flutter app. To do this I would like to access the camera data in a speedy manner.
As far as I can tell I have two options, and have hit roadblocks with both:
Take a screenshot of the CameraPreview by putting a RepaintBoundary around it and creating a RenderRepaintBoundary, and calling boundary.toImage(). The problem with this method is that the .toImage method only seems to capture the painted widgets in the boundary and not the data from the camera preview. Simmilar to the issue described here: https://github.com/flutter/flutter/issues/17687
Capture an image with controller.takePicture(filePath) from Camera 0.2.1, similar to the example docs. The problem here is that it takes super long before the image becomes available (2-3 seconds). I guess that this is because the file is saved to the disc on capture and then needs to be read from the file again.
Is there any way that one can directly access the picture information after capture, to do things like pre-process and OCR?
For "near real-time OCR", you need CameraController#startImageStream
example code
import 'package:camera/camera.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: _MyHomePage()));
class _MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<_MyHomePage> {
dynamic _scanResults;
CameraController _camera;
bool _isDetecting = false;
CameraLensDirection _direction = CameraLensDirection.back;
#override
void initState() {
super.initState();
_initializeCamera();
}
Future<CameraDescription> _getCamera(CameraLensDirection dir) async {
return await availableCameras().then(
(List<CameraDescription> cameras) => cameras.firstWhere(
(CameraDescription camera) => camera.lensDirection == dir,
),
);
}
void _initializeCamera() async {
_camera = CameraController(
await _getCamera(_direction),
defaultTargetPlatform == TargetPlatform.iOS
? ResolutionPreset.low
: ResolutionPreset.medium,
);
await _camera.initialize();
_camera.startImageStream((CameraImage image) {
if (_isDetecting) return;
_isDetecting = true;
try {
// await doSomethingWith(image)
} catch (e) {
// await handleExepction(e)
} finally {
_isDetecting = false;
}
});
}
Widget build(BuildContext context) {
return null;
}
}
This functionality was merged to https://github.com/flutter/plugins but it was not well documented.
Ref:
https://github.com/flutter/flutter/issues/26348
https://github.com/flutter/plugins/pull/965
https://github.com/bparrishMines/mlkit_demo/blob/master/lib/main.dart#L43
https://youtu.be/OAEWySye0BQ?t=1460
A better solution today (2022) for real-time OCR is to use the camera in a loop with a frequency of 500ms and process the image using google ML Kit's Text recognition.
public void addListenerOnButton()
{
final Context context = this;
inquiry = (Button)findViewById(R.id.btnInquiry);
link = (Button)findViewById(R.id.btnLink);
inquiry.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(context,QuickInquiry.class);
startActivity(i);
}
});
link.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(context,PortfolioFragment.class);
startActivity(i);
}
});
}
When I click on the button which should open the fragment, I get an exception that PortfolioFragment is not mentioned in the android manifest file. PortfolioFragment is the fragment java file.
You can only use Activity with startActivity().
From Android Documentation,
A Fragment represents a behavior or a portion of user interface in an
Activity. You can combine multiple fragments in a single activity to
build a multi-pane UI and reuse a fragment in multiple activities. You
can think of a fragment as a modular section of an activity, which has
its own lifecycle, receives its own input events, and which you can
add or remove while the activity is running (sort of like a "sub
activity" that you can reuse in different activities).
Here's a detailed explanation of Fragments:
http://developer.android.com/guide/components/fragments.html
I am creating an Android activity and starting a service from this activity using the following code. Now I want to display text "Hello user" from this service to screen, meaning service should trigger this display. I could use Toast.maketext.show but the display will disappear after couple of seconds.
new Thread(new Runnable() {
#Override
public void run() {
startAdapterIntent.setAction("START_ADAPTER");
startService(startAdapterIntent);
System.out.println("Thread2: Adapter Service started.");
}
}).start();
How do I do that?
I tried to use this link:
Making changes to Main Activity UI from thread in Service
and its (probably) parent link
http://developer.android.com/reference/android/app/Service.html
section "Remote Messenger Service Sample"
While using this second link, the onServiceConnected part of ServiceConnection doesn't seem to be working? Please help. Thank you.
From within your service you should create a handler that can be triggered by a timer task, the handler should be the one directly responsible of doing the communication with the currently active UI thread..an example would be
long delay = 3000;
long period = 3000;
TimerTask mDoTask = new TimerTask() {
#Override
public void run() {
xHandler.sendMessage(Message.obtain(xHandler, SOME_OPERATION));
}
};
mT.scheduleAtFixedRate(mDoTask, delay, period);
Handler xHandler=new Handler(){
#Override
public void handleMessage(Message message){
switch (message.what){
case SOME_OPERATION:
YourMethod();// in this method you can display your text
break;
}
}
};