Android Studio onAttach Deprecation Resolution? - android-fragments

So I've been following this Android Tutorial (Youtube) by Derek Banas. Trying to learn to make a NavigationDrawer.
I run into onAttach() being deprecated. I looked at this Stack Overflow link but I'm a beginner in AS and can't understand if it's correct (mainly due to me not sure if I have to instantiate MTitle, mCalled, mHost,etc) and how I can possibly implement it, in my app.
onAttach code:
public void onAttatch(Activity activity) {
super.onAttach(activity);
((MainActivity)activity).onSectionAttached(1);
}
public void onSectionAttached(int number) {
switch(number) {
case 1:
mTitle = getString(R.string.title_section1);
break;
}

Try
public void onAttach(Context context){
super.onAttach(context);
...
}

Related

How can I get NavigationService and navigate from a backdoor method?

I'm trying to navigate from a backdoor so that I can bypass a certain screen when running my UITests.
Here's my code:
AppDelegate.cs
[Export("bypassInitialGuidePage:")]
public NSString BypassInitialGuidePage(NSString noValue)
{
BackdoorHelpers.BypassInitialGuidePage();
return new NSString();
}
MainActivity.cs
[Export("BypassInitialGuidePage")]
public void BypassInitialGuidePage() => BackdoorHelpers.BypassInitialGuidePage();
BackdoorHelpers.cs
public static class BackdoorHelpers
{
#if DEBUG
public static void BypassInitialGuidePage()
{
new SettingsService().InitialGuideDone = true;
// Add navigation logic here
}
#endif
}
The BypassInitialGuidePage() method is being called successfully from the tests. However, I need help with getting the NavigationService so I can navigate away from current page.
I'm using Prism.Forms v7.1.0.431 and I've tried the solutions in https://github.com/PrismLibrary/Prism/issues/1032 but they are not working with the latest version.

Is it possible to delay-load PRISM / Xamarin Forms components that aren't immediately needed?

I have the following AppDelegate which takes quite some time to load:
Syncfusion.ListView.XForms.iOS.SfListViewRenderer.Init();
new Syncfusion.SfNumericUpDown.XForms.iOS.SfNumericUpDownRenderer();
Syncfusion.SfCarousel.XForms.iOS.SfCarouselRenderer.Init();
Syncfusion.XForms.iOS.Buttons.SfSegmentedControlRenderer.Init();
Syncfusion.XForms.iOS.Buttons.SfCheckBoxRenderer.Init();
new Syncfusion.XForms.iOS.ComboBox.SfComboBoxRenderer();
//Syncfusion.XForms.iOS.TabView.SfTabViewRenderer.Init();
new Syncfusion.SfRotator.XForms.iOS.SfRotatorRenderer();
new Syncfusion.SfRating.XForms.iOS.SfRatingRenderer();
new Syncfusion.SfBusyIndicator.XForms.iOS.SfBusyIndicatorRenderer();
What options should I consider when I know some of these components aren't needed for the main screen, but for subscreens?
I am using PRISM, and it appears that every tab is pre-loaded immediately before allowing display or interaction with the end user. What can I do to delay the pre-rendering that the Prism TabView does prior to showing the interface?
Should I use Lazy<T>? What is the right approach?
Should I move these components to another initialization section?
There are a number of ways you could ultimately achieve this, and it all depends on what your real goals are.
If your goal is to ensure that you get to a Xamarin.Forms Page as fast as possible so that you have some sort of activity indicator, that in essence says to the user, "it's ok I haven't frozen, we're just doing some stuff to get ready for you", then you might try creating a "SpashScreen" page where you do additional loading. The setup might look something like the following:
public partial class AppDelegate : FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App(new iOSInitializer()));
return base.FinishedLaunching(app, options);
}
}
}
public class iOSInitializer : IPlatformInitializer, IPlatformFinalizer
{
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterInstance<IPlatformFinalizer>(this);
}
public void Finalize()
{
new Syncfusion.SfNumericUpDown.XForms.iOS.SfNumericUpDownRenderer();
Syncfusion.SfCarousel.XForms.iOS.SfCarouselRenderer.Init();
Syncfusion.XForms.iOS.Buttons.SfSegmentedControlRenderer.Init();
Syncfusion.XForms.iOS.Buttons.SfCheckBoxRenderer.Init();
}
}
public class App : PrismApplication
{
protected override async void OnInitialized()
{
await NavigationService.NavigateAsync("SplashScreen");
}
}
public class SplashScreenViewModel : INavigationAware
{
private IPlatformFinalizer _platformFinalizer { get; }
private INavigationService _navigationService { get; }
public SplashScreenViewModel(INavigationService navigationService, IPlatformFinalizer platformFinalizer)
{
_navigationService = navigationService;
_platformFinalizer = platformFinalizer;
}
public async void OnNavigatedTo(INavigationParameters navigationParameters)
{
_platformFinalizer.Finalize();
await _navigationService.NavigateAsync("/MainPage");
}
}
If you're working with Modules you could take a similar approach though any Modules that would initialize at Startup would still be making that call to Init the renderers before you've set a Page to navigate to. That said, working with Modules does give you a number of benefits here as you only ever would have to initialize things that the app actually requires at that point.
All of that said I'd be surprised if you see much in the way of gain as these Init calls are typically empty methods only designed to prevent the Linker from linking them out... if you aren't linking or have a linker file you could simply instruct the Linker to leave your Syncfusion and other libraries alone.

DeploymentPlanExecutor.OnExecute not Being Called By SqlPackage.exe [duplicate]

I'm trying to program a custom DeploymentPlanExecutor using Microsofts DacFx 3.0 but the OnExecute-Method is never called.
If I use an identical DeploymentPlanModifier instead, OnExecute() is called as expected.
No matter whether I add the Executor, the Modifier, or both, the DAC actually is successfully deployed to the Database.
The Executor seems to be recognized during the Deployment since OnApplyDeploymentConfiguration() is called
Unfortunately I wasn't able to find any examples that use an DeploymentPlanExecutor (only examples with DeploymentPlanModifier) and the documentation of DacFx does not help at all.
My question is, why is OnExecute() in the DeploymentPlanExecutor not called and how can I fix this?
The code for my DeploymentPlanExecutor and DeploymentPlanExecutor:
using System.Collections.Generic;
using Microsoft.SqlServer.Dac.Deployment;
namespace DacTest
{
// The executor that does not work as expected
[ExportDeploymentPlanExecutor(ContributorId, "1.0.0.0")]
public class Executor : DeploymentPlanExecutor
{
public const string ContributorId = "DacTest.Executor";
protected override void OnApplyDeploymentConfiguration(DeploymentContributorContext context, ICollection<DeploymentContributorConfigurationStream> configurationStreams)
{
// Called
}
protected override void OnEstablishDeploymentConfiguration(DeploymentContributorConfigurationSetup setup)
{
// Not called
}
protected override void OnExecute(DeploymentPlanContributorContext context)
{
// Not called!
}
}
// The modifier that does work as expected
[ExportDeploymentPlanModifier(ContributorId, "1.0.0.0")]
public class Modifier : DeploymentPlanModifier
{
public const string ContributorId = "DacTest.Modifier";
protected override void OnApplyDeploymentConfiguration(DeploymentContributorContext context, ICollection<DeploymentContributorConfigurationStream> configurationStreams)
{
// Called
}
protected override void OnEstablishDeploymentConfiguration(DeploymentContributorConfigurationSetup setup)
{
// Not called
}
protected override void OnExecute(DeploymentPlanContributorContext context)
{
// Called!
}
}
}
The code calling the deployment (has to be in a different assembly):
using (DacPackage dacpac = DacPackage.Load(#"C:\Temp\dac.dacpac"))
{
DacDeployOptions dacDeployOptions = new DacDeployOptions();
dacDeployOptions.AdditionalDeploymentContributors = Executor.ContributorId; // + ";" + Modifier.ContributorId;
DacServices dacServices = new DacServices(connectionString);
dacServices.Deploy(dacpac, databaseName, true, dacDeployOptions);
}
The problem was, that you have to explicitly tell DacFx to use Executors. Modifiers are enabled by default though.
dacDeployOptions.RunDeploymentPlanExecutors = true;

JavaFX - Call "updateMessage" for TextArea from background Task - Two problems found

I am having two problems when trying to use "updateMessage" in a JavaFX task.
Issue #1
seems to be a known behavior, but I am not yet sure how exactly I can workaround it.This one is not (yet) critical to me.
The problem is that not all the updates I am performing in a background Task are displayed in the UI (at least the UI does not hang/freezes anymore, which was my initial issue).
My Code of the UI part:
TextArea console = new TextArea();
Button button01 = new Button("Start");
button01.setOnAction(new EventHandler() {
#Override
public void handle(Event event) {
if (ms.getState() == State.READY) {
ms.messageProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
console.appendText(newValue+"\n");
}
});
ms.start();
}
}
});
My Service:
public class MyService extends Service<Object> {
#Override
protected Task createTask() {
//here we use "MyTask" first to show problem #1
MyTask ct = new MyTask();
//here we use "MyTask2" first to show problem #2
// MyTask2 ct = new MyTask2();
try {
ct.call();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("MyService end");
return ct;
}
}
My Task (#1)
public class MyTask extends Task<Object> {
#Override
public EventHandler<WorkerStateEvent> call() {
System.out.println("call() is called");
if (Thread.currentThread().getName().equals("JavaFX Application Thread")){//yes, this might not be right, but if I do not do this, my stuff is executed twice because "call()" is called twice, but the textarea area is just updated in the second run (the non javafx application thread).
return null;
} else{
//actually here I want to do some 'heavy' stuff in the background
//and many things of this heavy stuff should be displayed / logged within the UI
//but very likely (hopefully) new messages (updateMessage) will not be send as fast as in the following loop
for (int i=0;i<10000000;i++){
updateMessage("This is update number'"+i+"' from the background thread");
}
Platform.runLater(new Runnable() {
#Override
public void run() {
try{
//here is the chance to get back to the view
}finally{
}
}
});
return null;
}
}
This basically works, but not every single loop is displayed in the UI.
How do I (correctly) make sure every loop is displayed?
Screenshot: Messages are displayed but not for every loop
Issue #2
Currently blocks my attempt to bring my little text-based game into a JavaFX application.
The main problem is that I am able to call "updateMessage" from the Task directly (see above), but not from a another (sub-)class which I would need to bring all message updates from my game (each message describes the progress of the game) to the UI.
The Task I use (Task #2):
public class MyTask2 extends Task<Object> {
#Override
public EventHandler<WorkerStateEvent> call() {
// ...
UITools myTools = new UITools();
myTools.logToUITest("Just one simple message");
// ...
Platform.runLater(new Runnable() {
#Override
public void run() {
try{
//here is the chance to get back to the view
}finally{
}
}
});
return null;
}
and the (sub-)class that I want to use to do the updateMessage (actually in my little game there would be even more classes that are called during the game and almost all of them trigger an update/message).
public class UITools {
public void logToUITest(String message){
updateMessage(message);
//how to allow 'updateMessage' from the Task to be executed from here?
}
This already results in "The method updateMessage(String) is undefined...".
How could I make it possible to call the updateMessage outside of the Task itself?
updateMessage() can only be called from within the call() method of a Task. It's a constraint imposed by the design of the Task class.
The missed message updates are due to the fact that there are too many updates and not all of them are forwarded to the event queue. Try to reduce the number of updates or sleep for a little while to separate them out in time

Android: When to register and unregister for notifications?

I use a Notifications interface to update fragments whenever data is changed.
public interface Notifications {
void register(ID id, Listener listener);
void unregister(ID id, Listener listener);
<T> void post(ID id, T value);
interface Listener<T> {
void onEvent(ID id, T value);
}
enum ID {
CustomersUpdated,
ProductsUpdated
}
}
With regards to the Android Lifecycle, what is the best point to register and unregister for notifications?
Here are some scenarios:
Scenario 1:
public class ProductsListFragment extends BaseFragment
implements Notifications.Listener {
#Override
public void onStart() {
mAdapter.notifyDataChanged();
register(Notifications.ID.ProductsUpdated, this)
super.onStart();
}
#Override
public void onStop() {
unregister(Notifications.ID.ProductsUpdated, this)
super.onStop();
}
#Override
public void onEvent(Notifications.ID id, Object value) {
mAdapter.notifyDataChanged();
}
Scenario 2:
public class ProductsListFragment extends BaseFragment
implements Notifications.Listener {
#Override
public void onResume() {
mAdapter.notifyDataChanged();
register(Notifications.ID.ProductsUpdated, this)
super.onResume();
}
#Override
public void onPause() {
unregister(Notifications.ID.ProductsUpdated, this)
super.onPause();
}
#Override
public void onEvent(Notifications.ID id, Object value) {
mAdapter.notifyDataChanged();
}
Please explain why you would suggest using one or the other implementation .. or another!
There isn't a universal answer to this question. onResume/onPause will probably give the expected behaviour most of the time but you might run into cases where you want to do it earlier or later.
On a different note, though, two points on style and functionality - call super.onResume as the first thing in the method (and super.onStop as the last). That way your cycle is entirely nested inside the "super" cycle and you avoid weird bugs and edge cases. Further, it's not a great idea to always call notifyDataSetChanged in onResume. In fact, it's probably a pretty wasteful idea.
I would stick with Scenario 2. Although the order in which onPause() and onResume() is linear for fragments, the same is not true for Activities.
Since the fragments' pause and resume are called whenever the activity's is, broadcasts would be received whenever the activity is active. However, the activity does not call onStop() until it loses visibility. In this case, the fragments would still process broadcasts while the activity it is contained in is inactive, which doesn't sound like a very good idea to me.

Resources