Beginner’s Guide: How to Use WordPress Block Patterns

Do you want to learn how to use WordPress block patterns on your website?

Block patterns allow you to quickly add commonly used design elements to your post or page layouts.

In this article, we’ll show you how to use WordPress block patterns and find more patterns to use on your website.

Using block patterns in WordPress

Here are the topics we’ll cover in this guide.

What are WordPress Block Patterns?

WordPress block patterns are a collection of pre-made design elements that you can use for creating custom content layouts faster.

WordPress comes with an intuitive editor commonly known as the block editor. It allows users to create beautiful layouts for their posts and pages using blocks for common content elements.

WordPress block editor

However, not all WordPress users are designers or want to spend time creating layouts each time they need to create a post or page.

Block patterns provide an easy solution to that problem. WordPress now comes with a bunch of useful block patterns by default.

Block patterns in WordPress

Popular WordPress themes also provide their own patterns that you can use when writing content.

These patterns include items like pre-built multi-column layouts, media and text patterns, call-to-action patterns, headers, buttons, and more.

You can find even more patterns on the WordPress.org website, and you can even create and share your own patterns as well.

That being said, let’s take a look at how to easily use block patterns in WordPress to create beautiful content for your website.

How to Use Block Patterns in WordPress

By default, WordPress comes with a bunch of useful block patterns that you can use on your website. Your WordPress theme and some plugins may also add their own patterns.

To use block patterns, you need to edit the WordPress post or page where you want to use the block pattern.

On the post edit screen, click on the Add Block button to open the block inserter. From here, switch to the Patterns tab to view available block patterns.

Add block pattern

You can scroll down to see available block patterns.

You can also view block patterns in different categories like featured, buttons, columns, header, and more.

Sort block patterns by category

Alternatively, you can also click on the Explore button to view block patterns.

Here you can see larger previews in a popup.

Block patterns preview

Once you find a pattern you want to try, you can simply click to insert it to the content area of your post or page.

Edit block pattern

After that, you can simply point and click on any block inside the pattern to edit and change its contents to your own requirements.

You’ll still have all the options you normally have for each block. For instance, if it is a cover block, then you can change the cover color or background image.

You can add as many patterns as you need for your blog post or page. You can also simply delete a pattern to remove it from a post or page like you would delete any WordPress block.

Remove cover block

By using block patterns, you can quickly make beautiful layouts for your articles and WordPress site.

Ultimately, block patterns help save you time that you would otherwise spend on manually arranging blocks each time you need to add a header, gallery, buttons, and more.

Finding More Block Patterns to Use on Your Website

By default, WordPress comes with a few commonly used block patterns. WordPress themes may also add their own patterns to your website.

However, you can find a lot more block patterns than the ones available under the block inserter on your website.

Simply go to the WordPress Patterns Directory website to view many more block patterns.

Block pattern directory

Here you’ll find many more block patterns submitted by the WordPress community.

To use one of these block patterns, simply take your mouse over to the block pattern and click on the Copy button.

Copy block pattern

Next, you need to go back to your WordPress blog and edit the post or page where you want to insert this block pattern.

On the post edit screen, simply right-click and select Paste in the browser menu or press CTRL+V (Command + V on Mac).

Paste block pattern

How to Create and Share Your Own Block Patterns

Want to create and share your own WordPress block patterns and share them with the world?

WordPress makes it super easy to create block patterns and use them on your own websites or share them with all WordPress users across the globe.

Simply visit the WordPress Pattern Directory website and click on the ‘Create New Pattern’ link.

Create block pattern

Note: You’ll need to sign in or create a free WordPress.org account to save your patterns.

Once signed in, you’ll reach the block pattern editor page. It is identical to the default WordPress block editor, and you can use it to create your pattern.

Block pattern creator

Simply add blocks to create your pattern layout.

You can use layout blocks like group, cover, gallery, and more to organize your layout.

Editing block pattern layout

There are also royalty-free images available to use in your media blocks. The WordPress media library will allow you to easily find and use these images in your patterns.

Once you are satisfied with your block pattern, you can save it as a draft or submit it to the pattern directory.

Before you can submit your block pattern for the pattern directory, make sure that you have read block pattern directory guidelines.

You can manage all your block patterns by clicking on the My Patterns link. It will show all block patterns you have shared, draft patterns, and patterns you have favorited.

Your patterns

If you only want to create block patterns for your own use, then you can save them as drafts. After that, you can simply copy and paste them from My Patterns page to your WordPress website.

Creating WordPress Block Patterns Manually

You can also create block patterns manually and add them to your WordPress theme or custom snippets plugin.

Simply create a new post or page in WordPress. In the content area, use blocks to create a custom layout or block collection that you want to save as a pattern.

Switch to the code editor

After that, switch to the Code Editor mode and copy all content you see in the code editor.

Copy raw code blocks

Next, open a plain text editor like Notepad and paste that code in there. You’ll need it in the next step.

Now you are ready to register your blocks as a pattern.

To do that, simply copy and paste the following code into your theme’s functions.php file or a site-specific plugin.

function wpb_my_block_patterns() {
    register_block_pattern(
        'my-plugin/my-awesome-pattern',
        array(
            'title'       => __( 'Two column magazine layout', 'my-theme'),
            'description' => _x( 'A simple magazine style two-column layout with large image and stylized text', 'my-theme' ),
            'categories'  => array( 'columns' ),
            'content'     => ' Your block content code goes here'
            )
    );
}
add_action( 'init', 'wpb_my_block_patterns' );

Now copy and paste the raw blocks data you copied earlier as the value for the content parameter. In other words, you’ll need to replace the text that says ‘Your block content code goes here’ with your block code. Be sure to leave the single quotes surrounding the text in place.

Lastly, don’t forget to change the title and description to your own and save your changes.

You can now visit your website and edit and post or page. You’ll now be able to see your newly registered block pattern in the block inserter.

Add custom block pattern to your post

Remove a Block Pattern in WordPress

You can easily remove or unregister any block pattern in WordPress. Let’s say you want to remove the block pattern you created in the above example.

All you need to do is copy paste the following code to your theme’s functions.php file or a site-specific plugin.

function wpb_unregister_my_patterns() {
  unregister_block_pattern( 'my-plugin/my-awesome-pattern' );
}
add_action( 'init', 'wpb_unregister_my_patterns' );

In this example, 'my-plugin/my-awesome-pattern' is the name of the pattern we used when registering it.

You can use this code to unregister any block pattern created by your theme or a plugin. All you need to know is the name used to register the pattern.

Remove Core WordPress Patterns

The core WordPress patterns are available to all WordPress users. This means they may be over used and might not even match rest of your WordPress theme.

If you don’t want to use a pattern, then you can simply avoid adding it to your content. However, if you run a multi author WordPress site, then you may want to prevent all users from using these core patterns.

To remove all core WordPress patterns, you need to add the following code to your theme’s functions file or a site-specific plugin.

remove_theme_support( 'core-block-patterns' );

What’s The Difference Between Reusable Blocks and Block Patterns?

Block patterns and reusable blocks both intend to solve a similar problem: provide users with options to easily add commonly used blocks.

However, they are quite different from each other.

For instance, reusable blocks can be edited and saved right inside the post editor, but they are not as flexible as block patterns.

One big difference is that if you make a change to a reusable block, it changes the block on every post or page you’ve used it on.

Reusable block in WordPress

For more details, see our tutorial on how to use reusable blocks in WordPress.

On the other hand, if you insert a pattern and edit it, then those changes only apply to the post or page where you have added that pattern.

Block patterns can also be registered by your WordPress theme or plugins such as block plugins. This allows those developers to offer you a lot more design options to create your post and page layouts.

We hope this guide helped you learn how to use WordPress block patterns on your website. You may also want to see our guide on how to choose the best web design software, or our expert pick of the best email marketing services for small business.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

The post Beginner’s Guide: How to Use WordPress Block Patterns first appeared on WPBeginner.

Build a Query in MuleSoft With Optional Parameters

In this tutorial we will see how to:

  • Define a RAML API specification to search products in a catalog database
  • Establish and configure a database connection to query a MySQL database
  • Build a query to support multiple optional filters
  • Add optional sorting capabilities to our query at DB level

1. Define the RAML of a Search API

Imagine that you want to create a MuleSoft API to search products inside a catalog. This API will need to accept multiple filter parameters and an optional sorting parameter. All these parameters can be optional and will be used to generate a dynamic query to search products in your catalog database.

Leveraging Change Data Capture for Fraud Detection using Arcion Cloud

During the height of the business intelligence (BI) craze earlier in my career, I worked with an internal reporting team to expose data for extract, transform, and load (ETL) processes that leveraged data structures inspired by Ralph Kimball. It was a new and exciting time in my life to understand how to optimize data for reporting and analysis. Honestly, the schema looked upside down to me, based on my experience with transaction-driven designs.

In the end, there were many moving parts and even some dependencies for the existence of a flat file to make sure everything worked properly. The reports ran quickly, but one key factor always bothered me: I was always looking at yesterday’s data.

How to access properties and methods passed in via an instance object.

class Namer (object):
    def __init__(self, arg):
        self.arg = arg

A = Namer("A")
B = Namer("B")
C = Namer("C")

print(A.arg)
print(B.arg)
print(C.arg)

class FrameIt(object):
    def __init__(self, content):
        #Namer.__init__(self, arg)   #<-----------?
        #super().__init__(self, arg) #<-----------?     
        self.content = content
        #super().__init__()  #<-------------------?

    def framed (self):
        print(self.content)

X = FrameIt(A)
Y = FrameIt(B)
Z = FrameIt(C)

print("\n")

X.content()  #<-----------  access properties?
Y.content()
Z.content()    

print("\n")  

X.framed()  #<------------ access method output? 

Generates output, like this:

TypeError: 'Namer' object is not callable

How to get to the good stuff in the instance?

Any help much appreciated.

Android Native – How to use PagingSource

Introduction

Among all of the Android libraries, Paging 3 is perhaps one of the hardest to understand.

Personally, I think the problem with Paging 3 are:

  1. Developers need to learn a lot of custom classes before they can understand how Paging 3 works under the hood and how to use the library to its fullest potential. The list of classes is long. It includes:

     CombinedLoadStates
     ConcatAdapter
     DiffUtil
     LoadState
     LoadStateAdapter
     LoadStates
     LoadType
     Pager
     PagingConfig
     PagingData
     PagingDataAdapter
     PagingSource
     PagingSource.LoadResult
     PagingState
     RemoteMediator
     RemoteMediator.MediatorResult
  2. You will have to dig deep into Pager/PagingDataAdapter source code to understand how PagingSource and PagingData are invalidated. Because you are not in control of creating PagingData yourself, how the PagingSource/PagingData pair is created and invalidated can be too magical for comfort.

  3. Unlike other libraries that only provide functionality for a specific layer, Paging 3 library classes span across multiple layers of your App: UI, ViewModel, Repository, Database.

On the bright side The final result is not a lot of code, and using this pre-made library would still most likely be simpler than rolling your own.

Paging 3 can operate in two different modes. The first mode only displays paged data from a network without an offline database as a cache. In the second mode, you can enlist a local Room database to use as your cache, for offline support.

In this tutorial, we will learn how to use Paging 3 without an offline database.

Goals

At the end of the tutorial, you would have learned:

  1. How to use PagingSource to display data from the network.
Tools Required
  1. Android Studio. The version used in this tutorial is Bumblebee 2021.1.1 Patch 3.
Prerequisite Knowledge
  1. Intermediate Android.
  2. MVVM.
  3. Hilt.
  4. Kotlin Flow.
  5. Retrofit.
  6. Moshi.
  7. ViewBinding.
  8. DataBinding.
Project Setup

To follow along with the tutorial, perform the steps below:

  1. Clone the sample app called CatFacts from https://github.com/dmitrilc/CatFacts.git
  2. Switch to the No_RemoteMediator branch.
Project Overview

The project is already completed, but we will walk through the built app to learn what happens at each step.

In the screenshot of the project structure below, we are only concerned about the classes in green. It is okay to ignore the packages and classes in red because they are not really interesting to the current topic; they are just Hilt and Retrofit classes if you are curious.

app_structure.png

You can run the app now. It is just a RecyclerView that displays cat facts received from the Cat Facts API. As you reach the end of the list, it will reach out to the network to get more data. You can also verify this behavior by using the Network Inspector. Refer to the animation below as a reference.

NoRemoteMediator.gif

The App also has a button to trigger a refresh, which causes Pager to reload data at a specified location.

App Architecture

To understand the apps architecture, we can refer to the diagram below.

NoRemoteMediatorArch.png

In the diagram above, how PagingDataAdapter loads another item is mostly hidden from us, so we can just call it implementation details. Because implementation details are subject to change, It is really not worth it to divulge them in this tutorial. Though if you are still confused and wants to know what happens, you can start with debugging backwards at the beginning of the CatFactPagingSource#load() function.

The classes PagingDataAdapter, MainActivity, CatFactsViewModel, CatFactRepo, Pager, and WebService all exist within the project code. This is what the app does:

  1. At first launch, the Repository prefetches enough data to display on the screen. It might load one or two pages, depending on the height of the screen and how many facts can fit.

  2. As the user scrolls to the bottom of the RecyclerView, PagingDataAdapter signals the Pager to load more items, invalidating the current generation (PagingSource/PagingData pair) as well as generating a new generation.

  3. After the new pair of PagingSource/PagingData is generated, a new PagingData object is pushed to the PagingDataAdapter.

  4. At the top of the App, there is a Button to to manually trigger a refresh() action. This app always start from the beginning because I am trying to avoid business logic overload in this tutorial, which can lead to unnecessary complexity. Just keep in mind that this refresh feature is very situational and not all Apps will need it, but we are still required to override it.

  5. I have also injected a callback into CatFactPagingSource, which can be used to update the UI of the last loaded page. This is just to confirm that the refresh is working correctly. This step is entirely optional.

Implementing PagingSource

When using Paging 3 without an offline database, you must first define a custom implementation of PagingSource yourself. The only two functions that you need to override are load() and getRefreshKey().

In CatFactPagingSource.kt, our implementation of load() is as below.

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, CatFact> {
   try {
       // Start refresh at page 1 if undefined.
       val position = params.key ?: CAT_FACTS_STARTING_PAGE_INDEX
       pageNumberUpdater(position)

       val response = webService.getCatFactPage(position)
       val catFacts = response.data

       val prevKey = if (position == CAT_FACTS_STARTING_PAGE_INDEX) {
           null //if current position is the same as the starting position
       } else {
           position - 1
       }

       val nextKey = if (catFacts.isEmpty()){
           null //if there is no more data to load in the current direction
       } else {
           position + 1
       }

       return LoadResult.Page(
           data = catFacts,
           prevKey = prevKey,
           nextKey = nextKey
       )
   } catch (exception: IOException) {
       return LoadResult.Error(exception)
   } catch (exception: HttpException) {
       return LoadResult.Error(exception)
   }
}

Let us go through this code line by line.

  1. The function load() has a parameter of type LoadParams. An internal implementation will provide the argument when it calls load(). The most important properties of LoadParams would be its public properties key and loadSize.

  2. Typically, the key usually come from 4 different places:
    A. The previous or the next key that you have provided to the previous generation, depending on the LoadType (APPEND or PREPEND).
    B. The key from the getRefreshKey() function.
    C. The initialKey property when constructing the Pager.
    D. A custom key defined by you. For example, in this App, we used the constant CAT_FACTS_STARTING_PAGE_INDEX as the initial key.

  3. The other property of LoadParams, loadSize indicates how many items to load. This is the number pageSize passed to the PagingConfig in the CatFactRepo.kt file. The load() function is not required to use this property if it does want to.

  4. You are in control of how you want to calculate the previous and next keys. This heavily depends on the remote API that you are fetching from. For this App, we simply add or subtract one to the current key depending on the scrolling direction.

  5. Lastly, we must return a LoadResult object, which can be a LoadResult.Page on success or LoadResult.Error/LoadResult.Invalid if something went wrong. All three classes Page, Error, and Invaliad are subclasses of LoadResult.

Next, we will have to override getRefreshKey() as well. Our current implementation is as below.

override fun getRefreshKey(state: PagingState<Int, CatFact>): Int? {
   /*
   This will always start loading from the beginning.
   Same effect as return AT_FACTS_STARTING_PAGE_INDEX.
   */
   return null
   //If you want the list to resume at page 5, return 5, etc..
}

We are simply returning null, which the load() function will receive and then resets the key back into CAT_FACTS_STARTING_PAGE_INDEX, which will starts loading page one or page two as well, depending on whether the loaded items can fill the viewport.

Creating a Pager

To connect the UI and the Data layers, we would need to use a Pager object. The code below illustrates how to create a Pager.

fun getCatFactPagerWithoutRemoteMediator(): Flow<PagingData<CatFact>> =
   Pager(
       config = PagingConfig(pageSize = 1)
   ) {
       CatFactPagingSource(webService){ page ->
           _currentPage.value = "$page"
       }
   }
       .flow

After creation, its only public property is flow, which can be collected in other layers. There exists an extension function that exposes this flow as a LiveData as well.

Creating the PagingDataAdapter

To consume the Flow<PagingData<T>>, we must use a special RecycleView Adapter called PagingDataAdapter.

class PagingCatFactAdapter : PagingDataAdapter<CatFact, PagingCatFactAdapter.CatFactViewHolder>(DiffCallback) {

   class CatFactViewHolder(val binding: CatFactBinding) : RecyclerView.ViewHolder(binding.root){}

   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
       CatFactViewHolder(
           CatFactBinding.inflate(
               LayoutInflater.from(parent.context),
               parent,
               false
           )
       )

   //Binds data to a viewholder
   override fun onBindViewHolder(holder: CatFactViewHolder, position: Int) {
       val item = getItem(position)
       if (item != null) {
           holder.binding.catFact.text = item.fact
       }
   }

   object DiffCallback : DiffUtil.ItemCallback<CatFact>() {
       override fun areItemsTheSame(old: CatFact, new: CatFact) = old == new
       override fun areContentsTheSame(old: CatFact, new: CatFact) = old.fact == new.fact
   }

}

The implementation is very similar to a normal adapter, there are only 3 main differences.

  1. You must subclass PagingDataAdapter.
  2. PagingDataAdapter requires a DiffUtil.ItemCallback in its constructor, which you must implement as well. Your implementation of DiffUtil.ItemCallback must know how to compare the objects and its contents.
  3. You do not have to implement getItemCount() yourself.
Connecting Pager to PagingDataAdapter

Lastly, we must collect the Flow from the Pager, and then submit it to PagingDataAdapter in the Activity or Fragment.

lifecycleScope.launch {
   viewModel.pagerNoRemoteMediator.collectLatest {
       adapter.submitData(it)
   }
}
Run the App

Now that we have understood everything, it is time to run the App again to see how the refresh functionality works.

NoRemoteMediator2.gif

Summary

Congratulations! We have learned how to use Paging 3 without offline support in this tutorial. If you are interested in learning how to use Paging 3 with offline support as well, check out the RemoteMediator tutorial here. The full project code can be found at https://github.com/dmitrilc/CatFacts/tree/No_RemoteMediator

Android Native – How to use RemoteMediator

Introduction

The Android Paging 3 library can operate in two modes, with an offline Room database as a source of truth or without one. In this tutorial, we will look at how to use Paging 3 with a local Room database.

This tutorial expands on the previously published Paging 3 tutorial without an offline database here. Paging 3 is somewhat complex, so if you are new to the library, I would recommend checking out the tutorial without RemoteMediator first.

Goals

At the end of the tutorial, you would have learned:

  1. How to use RemoteMediator with Paging 3.
Tools Required
  1. Android Studio. The version used in this tutorial is Bumblebee 2021.1.1 Patch 3.
Prerequisite Knowledge
  1. Intermediate Android.
  2. MVVM.
  3. Hilt.
  4. Kotlin Flow.
  5. Retrofit.
  6. Moshi.
  7. ViewBinding.
  8. DataBinding.
  9. Room.
  10. Basic SQL.
Project Setup

To follow along with the tutorial, perform the steps below:

  1. Clone the sample app called CatFacts from https://github.com/dmitrilc/CatFacts.git
  2. Switches to the With_RemoteMediator branch.
Project Overview

The project has been completed, but we will walk through the important classes to understand how RemoteMediator is used.

In the project structure below, the classes and packages in red can be ignored, while the ones in green are important to the topic.

app_structure_with_RemoteMediator.png

The App is very simple. It only loads Cat Facts from the Cat Facts API and displays them in a RecyclerView.

There are also some TextViews at the top of the screen to show statistics about the pages. This is only for demonstration purposes.

WithRemoteMediator.gif

App Architecture

The diagram PagingSource With RemoteMediator below attempts to explain the relationships among the classes in the current App. I have also included the diagram without RemoteMediator to make it easier for you to see the differences between the two.

WithAndWithoutRemoteMediator.png

RemoteMediator is required if we want to use Paging 3 with a local database. It has a couple of responsibilities:

  1. Determine what to do based on the LoadType of APPEND, PREPEND, or REFRESH.
  2. Queries more data from the WebService.
  3. Commit CRUDs on this new data to the local Room database. How Room talks to the Pager object is mostly implementation details.

The Pager only reaches out to the RemoteMediator if there is no more data to load from the database. You might have also noticed that we do not have to implement our own PagingSource in this case. This is because Room provides its own implementation for us, with both load() and getRefreshKey() implemented.

Implementing RemoteMediator

First, let us walk through the CatFactRemoteMediator class to see how it was implemented. When you provide an implementation of RemoteMediator, you are required to override two functions, load() and initialize().

In our App, the implementation of load() is as below.

override suspend fun load(
   loadType: LoadType,
   state: PagingState<Int, CatFact>
): MediatorResult {
   return try {
       val loadKey = when (loadType) {
           LoadType.REFRESH -> {
               catFactDao.deleteAll()
               remoteKeyDao.deleteAll()
               CAT_FACTS_STARTING_PAGE_INDEX
           }
           LoadType.PREPEND -> return MediatorResult.Success(true)
           LoadType.APPEND -> {
               val remoteKey = remoteKeyDao.get()!!

               if (remoteKey.currentPage == remoteKey.lastPage){
                   return MediatorResult.Success(true)
               }

               remoteKey.currentPage.plus(1)
           }
       }

       val response = webService.getCatFactPage(loadKey)

       database.withTransaction {
           remoteKeyDao.insertOrReplace(
               RemoteKey(
                   currentPage = response.current_page,
                   lastPage = response.last_page
               ))

           catFactDao.insertAll(response.data)
       }

       MediatorResult.Success(false)
   } catch (e: IOException) {
       MediatorResult.Error(e)
   } catch (e: HttpException) {
       MediatorResult.Error(e)
   }
}

In the function above, the most important things that we need to understand are:

  1. Because the load() function has so many responsibilities, it is often easy to get lost if you are looking at someone elses implementation because their app logic, business logic, and remote endpoints are different from yours. It is in your best interest to only understand how each function argument can be used to return the appropriate return value for your app.

  2. The LoadType parameter: this is just an enum with 3 values, APPEND, PREPEND, and REFRESH. APPEND and PREPEND represent the direction in which the user is scrolling, so you can handle this however you want based on your App behavior, such as loading the previous page or the next page. REFRESH is a little bit different, but you are in control of this as well; you can start loading from the beginning or resuming at a specific page. In this sample app, we clear everything and start from the beginning for REFRESH. For PREPEND, we return MediatorResult.Success with endOfPaginationReached set to true; this is akin to saying you have reached the end of pagination in this direction. For APPENDING, we are just incrementing the key by one.

  3. If the function has not been short-circuited by one of the return statements in the when expressions body, then we will request new data from the API and insert them into the Room database.

  4. We did not make use of the PagingState parameter at all. This is the same object that is passed to PagingSource#getRefreshKey(). It includes useful information such as the anchorPosition and the loaded pages. Again, you do not have to use it if it does not provide any useful information for your use case.

  5. We must return a MediatorResult object in the load() function as well. Do not confuse it with the LoadResult object from the PagingSources load() function. MediatorResult is a sealed class, so you cannot instantiate it directly. You must instantiate its subclasses Error and Success instead. If you are returning an Error, then you need to provide it with a Throwable object. If you are returning a Success, then you need to provide it with a boolean, indicating whether the end of paging has been reached for the current LoadType.

Next, we will need to implement initialize().

override suspend fun initialize(): InitializeAction {
   val remoteKey = remoteKeyDao.get()
   return if (remoteKey == null){
       InitializeAction.LAUNCH_INITIAL_REFRESH
   } else {
       InitializeAction.SKIP_INITIAL_REFRESH
   }
}

In this function, you can decide whether to perform an initial load or not. Fortunately, InitializeAction is just a simple enum with two constants. You do not have any dependency passed to initialize(), so you will have to rely on the WebService or the database objects in your own RemoteMediator class to decide whether you would like to refresh.

Creating the Pager

Creating a Pager when using a RemoteMediator is almost the same as without one, the only extra step that you need to do is to provide a RemoteMediator object to the Pagers remoteMediator parameter.

fun getCatFactPagerWithRemoteMediator(): Flow<PagingData<CatFact>> =
   Pager(
       PagingConfig(1),
       remoteMediator = catFactRemoteMediator
   ) {
       catFactDao.pagingSource()
   }
       .flow
Returning PagingSource<K, V> from Room

Another very important step that you need to do is to return a PagingSource from your DAO query. Our query is located in the CatFactDao.kt file.

@Query("SELECT * FROM cat_fact")
fun pagingSource(): PagingSource<Int, CatFact>

This part is a bit weird because we are not in control of how PagingSource is created by the generated DAO. It is a bit clearer when we look at the generated source code though.

@Override
public PagingSource<Integer, CatFact> pagingSource() {
 final String _sql = "SELECT * FROM cat_fact";
 final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
 return new LimitOffsetPagingSource<CatFact>(_statement, __db, "cat_fact") {
   @Override
   protected List<CatFact> convertRows(Cursor cursor) {
     final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(cursor, "id");
     final int _cursorIndexOfFact = CursorUtil.getColumnIndexOrThrow(cursor, "fact");
     final int _cursorIndexOfLength = CursorUtil.getColumnIndexOrThrow(cursor, "length");
     final List<CatFact> _result = new ArrayList<CatFact>(cursor.getCount());
     while(cursor.moveToNext()) {
       final CatFact _item;
       final int _tmpId;
       _tmpId = cursor.getInt(_cursorIndexOfId);
       final String _tmpFact;
       if (cursor.isNull(_cursorIndexOfFact)) {
         _tmpFact = null;
       } else {
         _tmpFact = cursor.getString(_cursorIndexOfFact);
       }
       final int _tmpLength;
       _tmpLength = cursor.getInt(_cursorIndexOfLength);
       _item = new CatFact(_tmpId,_tmpFact,_tmpLength);
       _result.add(_item);
     }
     return _result;
   }
 };
}

The code above is generated (Java), so it is a bit hard to read, but not that hard. After investigating, I have broken it down to several steps:

  1. It provides a concrete implementation of LimitOffsetPagingSource, overriding the method convertRows(Cursor cursor).
  2. LimitOffsetPagingSource is a subclass of PagingSource.
  3. The Cursor is looped through, creating CatFact objects and then place everything inside an ArrayList.
Managing the remote key

When using RemoteMediator with an offline database, Google recommends developers to create another entity for managing remote keys. How you build your key is highly dependent on what the remote data APIs return.

For the Cat Facts API specifically, the prev and next keys are provided with a paginated query, but they also provided a last_page key, and I have decided use that for simplicity instead of the prev and next keys, which are in nullable string form and changes for every query. You can check out the files RemoteKey and RemoteKeyDao to see how the keys are stored.

Unlike RemoteMediator, the Paging library is not at all aware of the key table, so you are in control of storing and using them however you want. Because the data is stored locally, it makes a lot of sense to create another table for managing the keys as well. The benefit with this approach is that you can apply data integration features that Room provides (foreign key, indexes, constraints, relationships, etc).

Consuming in Activity

To consume the Flow exposed from the Repository, we would consume it the same way when not using RemoteMediator as well.

lifecycleScope.launch {
   viewModel.pagerWithRemoteMediator.collectLatest {
       adapter.submitData(it)
   }
}
Summary

Congratulations! We have learned how to use Paging 3 with a RemoteMediator in this tutorial. The full project code can be found at https://github.com/dmitrilc/CatFacts/tree/With_RemoteMediator.

Making Machine Learning More Accessible for Application Developers

Introduction

Attempts at hand-crafting algorithms for understanding human-generated content have generally been unsuccessful. For example, it is difficult for a computer to “grasp” the semantic content of an image - e.g., a car, cat, coat, etc....… - purely by analyzing its low-level pixels. Color histograms and feature detectors worked to a certain extent, but they were rarely accurate for most applications.

In the past decade, the combination of big data and deep learning has fundamentally changed the way we approach computer vision, natural language processing, and other machine learning (ML) applications; tasks ranging from spam email detection to realistic text-to-video synthesis have seen incredible strides, with accuracy metrics on specific tasks reaching superhuman levels. A significant positive side effect of these improvements is an increase in the use of embedding vectors, i.e., model artifacts generated by taking an intermediate result within a deep neural network. OpenAI’s docs page gives an excellent overview:

Cpu upgrade help

recently I got a CPU upgrade taking my Ryzen 3 3100x to Ryzen 5 5600x. So after I installed the CPU ran into thermal issues no problem added some thermal paste and boom my pc booted ,but it wasn't the same before I could run Elden ring on a smooth 50-60fps but when I tried to open elven ring (or any heavy game) and boom my pc would crash and reboot and turn back on. At first me and my friends thought it was because we forgot to update the CPU I updated it: no luck with that. We tried reinstalling the CPU. no luck with that. then I downloaded Ryzen master and my PPT (CPU socket power was going red) and my temp 40C. we thought it was the power supply but 600Watts should have been more than enough on my setup(setup at bottom). My friend told me to get a new motherboard as it may not be able to handle that much electricity through its circuit. and that's where I'm at I'm too scared to put a new motherboard at I've never built a PC from scratch but if I have to I will I just want to make sure that is the problem. please help I spent all my money on this. if you need any more info please let me know Setup: Invidia card: Geforce 1660xTi CPU: 6 core Ryzen 5 5600x 3.8 gghz (Wraith stock cooler) Motherboard: B450m Asrock 16G ram Power supply: Helios Ei-600g gold (600 wattage) 3 outtake fans 1 intake fan Windows 11 1TB NVMe SSD

The 5 Healthcare AI Trends Technologists Need to Know

Healthcare has been at the epicenter of everything we do for two years. While the pandemic has been a significant driver of the conversation, healthcare technology—artificial intelligence (AI) specifically—has been experiencing explosive growth. One only needs to look at the funding landscape: more than 40 startups have raised at least $20 million in funding specifically to build AI solutions for healthcare applications.

But what’s driving this growth? The venture capital trail alone won’t help us understand the trends contributing to AI adoption in healthcare. But the “2022 AI in Healthcare Survey” will. For the second year, Gradient Flow and John Snow Labs asked 300 global respondents what they’re experiencing in their AI programs—from the individuals using them to the challenges and the criteria used to build solutions and validate models. These are the top five trends that emerged from the research. 

Mule Application Deployment to Cloudhub Using Connected App

In this article, we will create a Mule application and deploy the same to the cloud hub using Connected App. 

Connected APP

The Connected Apps feature provides a framework that enables an external application to integrate with the Anypoint Platform using APIs through OAuth 2.0 and OpenID Connect. Connected apps help users delegate their access without sharing sensitive credentials or giving complete control of their accounts to third parties. Actions taken by connected apps are audited, and users can also revoke access. Note that some products do not currently include client IDs of the Connected Apps features. The Connected Apps feature enables you to use secure authentication protocols and control an app’s access to user data. Additionally, end-users can authorize the app to access their Anypoint Platform data.

How to Start Using Natural Language Processing With PyTorch

Natural language processing (NLP) is continuing to grow in popularity, and necessity, as artificial intelligence and deep learning programs grow and thrive in the coming years. Natural language processing with PyTorch is the best bet to implement these programs.

In this guide, we will address some of the obvious questions that may arise when starting to dive into natural language processing, but we will also engage with deeper questions and give you the right steps to get started working on your own NLP programs.

How to Set Up and Run PostgreSQL Change Data Capture

The architecture of modern web applications consists of several software components such as dashboards, analytics, databases, data lakes, caches, search, etc.

The database is usually the core part of any application. Real-time data updates keep disparate data systems in continuous sync and respond quickly to new information. So how to keep your application ecosystem in sync? How do these other components get information about changes in the database? Change Data Capture or CDC refers to any solution that identifies new or changed data.

Using Unsupervised Learning to Combat Cyber Threats

As the world enters a digital age, cyber threats are rising with massive data breaches, hacks into personal and financial data, and any other digital source that people can exploit. To combat these attacks, security experts are increasingly tapping into AI to stay a step ahead, using every tool in their toolbox, including unsupervised learning methods.

Machine learning in the cybersecurity space is still in its infancy stage, but there has been a lot of traction since 2020 to have more AI involved in combating cyber threats.

How to Auto-Download Podcasts to Google Drive with Google Sheets

This tutorial describes how you can use Google Sheets to build your own podcast manager. You can specify a list of your favorite podcast shows in Google Sheets and it will automatically download new episodes to your Google Drive in neatly organized folders.

The setup is very simple, the app is completely open-source and you need no programming language.

How the Drive Podcast Manager Works?

You have to place the links of your favorite podcasts in column A of the Google Sheet as shown in the screenshot below.

Podcasts to Google Drive

The app will automatically download the latest episodes of each podcast to your Google Drive. You can open the MP3 files from your Google Drive or find them directly inside the same Google Sheet.

Google Sheets Podcast List

The app will create a new folder, titled Podcasts in your Google Drive. Inside this folder, it will create sub-folders for each podcast show with the folder name same as the title of the podcast.

Google Drive Podcasts Folder

Download Podcasts to Google Drive

Here’s how you can build your own podcast manager with Google Sheets and Google Drive.

  1. Click here to make a copy of the Google Sheet in your Google account.

  2. Open the copied spreadsheet, switch to the Subscriptions sheet and enter the RSS feed links of your favorite podcasts in column A. You may use our Apple Podcasts Lookup utility to find the RSS feed of any podcast that is listed on Apple Podcasts.

  3. Go to the Extensions menu and choose Script Editor to open the underlying Google Apps Script file.

  4. Choose the Install function from the list of functions and click Run to install the app. You may have to authorize the app once since it needs permission to save files to Google Drive on your behalf.

That’s it. The app will create a cron job that runs every few hours in the background and download the latest episodes of your favorite podcasts to your Google Drive.

We even have a built-in MP3 player embedded inside Google Sheets that will play the latest episode of each podcast when you click the Play button.

MP3 Player in Google Sheets

The Technical Details

If you are curious to know how the whole thing works, here’re the technical details.

The app uses the Spreadsheet API to read the list of podcasts from the Google Sheet. It then uses the XML service of Apps Script to parse the RSS feed and extract new podcast episodes that have been published since the last check.

All podcast RSS feeds are required to have an <item> tag with a <enclosure> tag inside. The <enclosure> tag contains the URL of the MP3 file and this is what the app uses to get the download URL of the corresponding episode.

const parseRSS = (xmlUrl, lastUpdatedTime) => {
  const feed = UrlFetchApp.fetch(xmlUrl).getContentText();
  const doc = XmlService.parse(feed);
  const root = doc.getRootElement();
  const channel = root.getChild('channel');
  const episodes = channel
    .getChildren('item')
    .map((item) => ({
      date: new Date(item.getChildText('pubDate')),
      title: item.getChildText('title'),
      enclosure: item.getChild('enclosure')?.getAttribute('url')?.getValue(),
    }))
    .filter(({ date }) => date > lastUpdatedTime)
    .filter(({ enclosure }) => enclosure);
  return { title: channel.getChildText('title'), episodes };
};

Once the app has a list of new episodes, it uses the UrlFetch service to download the podcasts and saves them to Google Drive in a folder specific to the podcast show.

The app then writes a new row to the Google Sheet with the link of the Google Drive file and a timestamp of when the episode was downloaded.

const getPodcastFolder = (folderName) => {
  const parentFolder = DriveApp.getFoldersByName('Podcasts').next();
  const folders = parentFolder.getFoldersByName(folderName);
  if (folders.hasNext()) return folders.next();
  return parentFolder.createFolder(folderName);
};

const downloadPodcast = (podcastTitle, episodeUrl, episodeTitle) => {
  try {
    const blob = UrlFetchApp.fetch(episodeUrl).getBlob();
    const folder = getPodcastFolder(podcastTitle);
    const file = folder.createFile(blob);
    SpreadsheetApp.getActiveSheet().appendRow([
      new Date(),
      `=HYPERLINK("${episodeUrl}";"${episodeTitle}")`,
      `https://drive.google.com/file/d/${file.getId()}/view`,
    ]);
  } catch (f) {
    console.error(f);
  }
};

Develop XR With Oracle, Ep 3: Computer Vision AI, ML, and Metaverse

This is the third piece in a series on developing XR applications and experiences using Oracle and focuses on XR applications of computer vision AI and ML and its related use in the metaverse.  Find the links to the first two articles below: 

As with the previous posts, here I will again specifically show applications developed with Oracle database and cloud technologies HoloLens 2, Mixed Reality Toolkit, and Unity platform.

10 Top File Sharing APIs

Sharing files with friends and co-workers has had a long history of evolution. In the early days (1980s) , it was done via a telephone line and a modem, hard copy files such as floppy disks, and then moved on to File Transfer Protocol (FTP) from a central server.

How to implement Infocards using interfaces in dotnet?

Hello guys am trying to implement Info Cards using the IInfoCard and IInfoCardFactory and IInfocards interfaces. If you know how to complete the methods of these interfaces to make a program show the forms for the respective categories, then you might just be the guy to help me. I have the interface code as below.

using System;
using System.Windows.Forms;

public interface IInfoCard
{
    string Name { get; set; }
    string Category { get; }
    string GetDataAsString();
    void DisplayData(Panel displayPanel);
    void CloseDisplay();
    bool EditData();
}

and then the interface for IInfoCardFactory

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public interface IInfoCardFactory
{
    IInfoCard CreateNewInfoCard(string category);
    IInfoCard CreateInfoCard(string initialDetails);
    string[] CategoriesSupported { get; }
    string GetDescription(string category);
}

How do I complete the methods in the class below to make them create the needed info cards and save data to a file

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace Assignment
{
    internal class CreditCardInfo : IInfoCardFactory,IInfoCard
    {
        private string[] categories = new string[] { "Credit Card" };
        private string name;

        public string[] CategoriesSupported
        {
            get { return categories; }
            set { categories = value; } 

        }

        public string Name { get
            {
                return this.name;   
            } 
            set { this.name = value; }  
        }

        public string Category
        {
            get
            {
                return this.Name;   
            }
            set
            {
                this.Name = value;
            }
        }

        public void CloseDisplay()
        {

            return;
        }

        public IInfoCard CreateInfoCard(string initialDetails)
        {
            string[] stringToSplit = initialDetails.Split(new char[] { '|' });
            string category = stringToSplit[0];
            string description = stringToSplit[1];
            CreditCardInfo info = new CreditCardInfo();
            info.CategoriesSupported=categories;
            return  info;
        }

        public IInfoCard CreateNewInfoCard(string category)
        {
            CreditCardInfo info= new CreditCardInfo();
            info.Category = category;
            return info;
        }

        public void DisplayData(Panel displayPanel)
        {
            //get the string[] categories and display
            string text = this.GetDataAsString();
            string[] info=text.Split(new char[] { '|' });   
            CreditCardDetails form=new CreditCardDetails();
            for(int i=0;i<form.Controls.Count;i++)
            {
                if (form.Controls[i].Name == "label7")
                {
                    form.Controls[i].Text = info[0];
                }
            }
            form.Show();    

        }
        public bool EditData()
        {
            new CreditCardForm().ShowDialog();
            return true;
        }

        public string GetDataAsString()
        {
            string data = this.Name;
            if(categories.Length > 0)
            {
                data+=categories[0].ToString();
            }
            return data;
        }

        public string GetDescription(string category)
        {
            if (category == "Credit Card")
                return "Save personal info about your credit card";
            else
                return "";


        }
    }
}